Merge remote-tracking branch 'antennapod/develop' into per_feed_playbackspeed

This commit is contained in:
Jonas Kalderstam 2019-10-05 01:18:14 +02:00
commit 97aa360611
397 changed files with 3730 additions and 2876 deletions

View File

@ -1,39 +1,74 @@
version: 2
version: 2.1
jobs:
build:
parameters:
build-steps:
description: "Steps that will be executed for this build"
type: steps
default: []
docker:
- image: circleci/android:api-28
working_directory: ~/AntennaPod
environment:
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx1536m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError"'
_JAVA_OPTIONS: "-Xms256m -Xmx1280m"
steps:
- checkout
- restore_cache:
keys:
- v1-android-{{ checksum "build.gradle" }}
# fallback to using the latest cache if no exact match is found
- v1-android-
- run:
# To build release, we need to create a temporary keystore that can be used to sign the app
command: |
keytool -noprompt -genkey -v -keystore "app/keystore" -alias alias -storepass password -keypass password -keyalg RSA -validity 10 -dname "CN=antennapod.org, OU=dummy, O=dummy, L=dummy, S=dummy, C=US"
./gradlew assembleRelease :core:testPlayReleaseUnitTest :app:assemblePlayDebugAndroidTest -PdisablePreDex
no_output_timeout: 1800
- store_artifacts:
path: app/build/outputs/apk
destination: apks
name: Create temporary release keystore
command: keytool -noprompt -genkey -v -keystore "app/keystore" -alias alias -storepass password -keypass password -keyalg RSA -validity 10 -dname "CN=antennapod.org, OU=dummy, O=dummy, L=dummy, S=dummy, C=US"
- steps: << parameters.build-steps >>
- save_cache:
paths:
- ~/.android
- ~/.gradle
- ~/android
key: v1-android-{{ checksum "build.gradle" }}
workflows:
unit-tests:
jobs:
- build:
name: Build debug
build-steps:
- run:
name: Build debug
command: ./gradlew assembleDebug -PdisablePreDex
- run:
name: Execute debug unit tests
command: ./gradlew :core:testPlayDebugUnitTest -PdisablePreDex
- build:
name: Build release
build-steps:
- run:
name: Build release
command: ./gradlew assembleRelease -PdisablePreDex
- run:
name: Execute release unit tests
command: ./gradlew :core:testPlayReleaseUnitTest -PdisablePreDex
- build:
name: Build integration tests
build-steps:
- run:
name: Build integration tests
command: ./gradlew :app:assemblePlayDebugAndroidTest -PdisablePreDex
- build:
name: Build free
build-steps:
- run:
name: Build free (for F-Droid)
command: ./gradlew assembleFreeRelease -PdisablePreDex -PfreeBuild
static-analysis:
jobs:
- build:
name: Checkstyle
build-steps:
- run:
name: Checkstyle
command: ./gradlew checkstyle

1
.gitignore vendored
View File

@ -16,7 +16,6 @@ build/
# Local configuration file (sdk path, etc)
local.properties
gradle.properties
.gradle
build.xml

View File

@ -24,7 +24,7 @@ trans.gl = core/src/main/res/values-gl-rES/strings.xml
trans.he_IL = core/src/main/res/values-iw-rIL/strings.xml
trans.hi_IN = core/src/main/res/values-hi-rIN/strings.xml
trans.hu = core/src/main/res/values-hu/strings.xml
trans.id = core/src/main/res/values-id/strings.xml
trans.id = core/src/main/res/values-in/strings.xml
trans.it_IT = core/src/main/res/values-it/strings.xml
trans.is = core/src/main/res/values-is-rIS/strings.xml
trans.ja = core/src/main/res/values-ja/strings.xml

View File

@ -1,6 +1,17 @@
Change Log
==========
Version 1.7.3
-------------
* Display episode image on widget (by @brad)
* Added checkbox to keep queue sorted (by @damoasda)
* New UI for "Add podcast" screen (by @ByteHamster)
* Added batch editing to the queue (by @ByteHamster)
* Added option to adapt remaining time to playback speed (by @CedricCabessa)
* Removed broken Flattr integration (by @ByteHamster)
* Added filter to "All episodes" list (by @jhunnius)
* Tons of bug fixes and performance improvements
Version 1.7.2
-------------
* Added configurable behavior of the back button

View File

@ -18,10 +18,10 @@ android {
// "1.2.3-SNAPSHOT" -> 1020300
// "1.2.3-RC4" -> 1020304
// "1.2.3" -> 1020395
versionCode 1070306
versionName "1.7.3-RC6"
versionCode 1070396
versionName "1.7.3b"
testApplicationId "de.test.antennapod"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
generatedDensities = []
javaCompileOptions {
@ -131,18 +131,14 @@ dependencies {
} else {
System.out.println("app: free build hack, skipping some dependencies")
}
implementation "com.android.support:support-v4:$supportVersion"
implementation "com.android.support:appcompat-v7:$supportVersion"
implementation "com.android.support:design:$supportVersion"
implementation "com.android.support:preference-v14:$supportVersion"
implementation "com.android.support:gridlayout-v7:$supportVersion"
implementation "com.android.support:recyclerview-v7:$supportVersion"
compileOnly 'com.google.android.wearable:wearable:2.2.0'
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.preference:preference:1.1.0"
implementation "androidx.gridlayout:gridlayout:1.0.0"
implementation "androidx.recyclerview:recyclerview:1.0.0"
implementation "androidx.media:media:1.1.0"
implementation "com.google.android.material:material:1.0.0"
annotationProcessor "androidx.annotation:annotation:1.1.0"
compileOnly "com.google.android.wearable:wearable:$wearableSupportVersion"
implementation "org.apache.commons:commons-lang3:$commonslangVersion"
implementation "commons-io:commons-io:$commonsioVersion"
implementation "org.jsoup:jsoup:$jsoupVersion"
@ -162,26 +158,21 @@ dependencies {
transitive = true
}
implementation "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion"
implementation("com.githang:viewpagerindicator:2.5.1@aar") {
exclude module: "support-v4"
}
implementation "com.githang:viewpagerindicator:2.5.1@aar"
implementation "com.github.shts:TriangleLabelView:$triangleLabelViewVersion"
implementation 'com.leinardi.android:speed-dial:1.0.2' // 1.0.2 uses support 27.1.1 ; newer versions use 28.0.0;
implementation 'com.leinardi.android:speed-dial:3.0.0'
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
implementation 'com.github.mfietz:fyydlin:v0.4.2'
implementation 'com.github.ByteHamster:SearchPreference:v1.3.0'
implementation "org.awaitility:awaitility:$awaitilityVersion"
androidTestImplementation "org.awaitility:awaitility:$awaitilityVersion"
androidTestImplementation 'com.nanohttpd:nanohttpd-webserver:2.1.1'
androidTestImplementation "com.jayway.android.robotium:robotium-solo:$robotiumSoloVersion"
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-intents:3.0.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0'
}
if (project.hasProperty("antennaPodServiceAccountEmail")) {
@ -193,20 +184,14 @@ if (project.hasProperty("antennaPodServiceAccountEmail")) {
}
}
// about.html is templatized so that we can automatically insert
// our version string in to it at build time.
task filterAbout {
inputs.files files(["src/main/templates/about.html",
"src/main/AndroidManifest.xml"])
outputs.file "src/main/assets/about.html"
} doLast {
copy {
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,
year : new Date().format('yyyy')])
}
task filterAbout(type: Copy) {
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,
year : new Date().format('yyyy')])
outputs.upToDateWhen { false }
}
task copyTextFiles(type: Copy) {
@ -216,6 +201,7 @@ task copyTextFiles(type: Copy) {
rename { String fileName ->
fileName + ".txt"
}
outputs.upToDateWhen { false }
}
preBuild.dependsOn filterAbout, copyTextFiles

View File

@ -66,13 +66,13 @@
# for retrolambda
-dontwarn java.lang.invoke.*
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.** { *; }
-keep class !android.support.v7.internal.view.menu.**,android.support.v7.** {*;}
-keep interface android.support.v7.** { *; }
-keep class com.google.android.wearable.** { *; }
-dontwarn android.support.v4.**
-dontwarn android.support.v7.**
-dontwarn com.google.android.material.**
-keep class com.google.android.material.** { *; }
-dontwarn androidx.**
-keep class androidx.** { *; }
-keep interface androidx.** { *; }
-dontwarn com.google.android.wearable.**
-keep class org.apache.commons.** { *; }

View File

@ -0,0 +1,52 @@
package de.danoeh.antennapod.core.service.download;
import androidx.annotation.NonNull;
import de.danoeh.antennapod.core.util.Consumer;
public class StubDownloader extends Downloader {
private final long downloadTime;
@NonNull
private final Consumer<DownloadStatus> onDownloadComplete;
public StubDownloader(@NonNull DownloadRequest request, long downloadTime, @NonNull Consumer<DownloadStatus> onDownloadComplete) {
super(request);
this.downloadTime = downloadTime;
this.onDownloadComplete = onDownloadComplete;
}
@Override
protected void download() {
try {
Thread.sleep(downloadTime);
} catch (Throwable t) {
t.printStackTrace();
}
onDownloadComplete.accept(result);
}
@NonNull
@Override
public DownloadRequest getDownloadRequest() {
return super.getDownloadRequest();
}
@NonNull
@Override
public DownloadStatus getResult() {
return super.getResult();
}
@Override
public boolean isFinished() {
return super.isFinished();
}
@Override
public void cancel() {
super.cancel();
result.setCancelled();
}
}

View File

@ -1,33 +1,31 @@
package de.test.antennapod;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.StringRes;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.PerformException;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.contrib.DrawerActions;
import android.support.test.espresso.contrib.RecyclerViewActions;
import android.support.test.espresso.util.HumanReadables;
import android.support.test.espresso.util.TreeIterables;
import androidx.annotation.StringRes;
import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.PerformException;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.contrib.DrawerActions;
import androidx.test.espresso.contrib.RecyclerViewActions;
import androidx.test.espresso.util.HumanReadables;
import androidx.test.espresso.util.TreeIterables;
import android.view.View;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.dialog.RatingDialog;
import de.danoeh.antennapod.fragment.QueueFragment;
import org.hamcrest.Matcher;
import java.io.File;
import java.util.concurrent.TimeoutException;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
public class EspressoTestUtils {
/**
@ -115,7 +113,7 @@ public class EspressoTestUtils {
}
public static void clickPreference(@StringRes int title) {
onView(withId(R.id.list)).perform(
onView(withId(R.id.recycler_view)).perform(
RecyclerViewActions.actionOnItem(hasDescendant(withText(title)),
click()));
}

View File

@ -4,9 +4,9 @@ import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import org.junit.After;

View File

@ -1,6 +1,6 @@
package de.test.antennapod.feed;
import android.support.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.FeedFilter;
import de.danoeh.antennapod.core.feed.FeedItem;
import org.junit.Test;

View File

@ -1,6 +1,6 @@
package de.test.antennapod.feed;
import android.support.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.FeedItem;
import org.junit.Test;

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.support.test.runner.AndroidJUnit4;
import androidx.test.runner.AndroidJUnit4;
import de.danoeh.antennapod.core.gpoddernet.GpodnetService;
import de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice;

View File

@ -1,8 +1,8 @@
package de.test.antennapod.handler;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -12,7 +12,6 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

View File

@ -0,0 +1,127 @@
package de.test.antennapod.service.download;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionTimeoutException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
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.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.service.download.StubDownloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Consumer;
import static de.test.antennapod.util.event.FeedItemEventListener.withFeedItemEventListener;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @see HttpDownloaderTest for the test of actual download (and saving the file)
*/
@RunWith(AndroidJUnit4.class)
public class DownloadServiceTest {
private CountDownLatch latch = null;
private Feed testFeed = null;
private FeedMedia testMedia11 = null;
private DownloadService.DownloaderFactory origFactory = null;
@Before
public void setUp() throws Exception {
origFactory = DownloadService.getDownloaderFactory();
testFeed = setUpTestFeeds();
testMedia11 = testFeed.getItemAtIndex(0).getMedia();
}
private Feed setUpTestFeeds() throws Exception {
Feed feed = new Feed("url", null, "Test Feed title 1");
List<FeedItem> items = new ArrayList<>();
feed.setItems(items);
FeedItem item1 = new FeedItem(0, "Item 1-1", "Item 1-1", "url", new Date(), FeedItem.NEW, feed);
items.add(item1);
FeedMedia media1 = new FeedMedia(0, item1, 123, 1, 1, "audio/mp3", null, "http://example.com/episode.mp3", false, null, 0, 0);
item1.setMedia(media1);
DBWriter.setFeedItem(item1).get();
return feed;
}
@After
public void tearDown() throws Exception {
DownloadService.setDownloaderFactory(origFactory);
}
@Test
public void testEventsGeneratedCaseMediaDownloadSuccess() throws Exception {
// create a stub download that returns successful
//
// OPEN: Ideally, I'd like the download time long enough so that multiple in-progress DownloadEvents
// are generated (to simulate typical download), but it'll make download time quite long (1-2 seconds)
// to do so
DownloadService.setDownloaderFactory(new StubDownloaderFactory(50, downloadStatus -> {
downloadStatus.setSuccessful();
}));
withFeedItemEventListener(feedItemEventListener -> {
try {
assertEquals(0, feedItemEventListener.getEvents().size());
assertFalse("The media in test should not yet been downloaded",
DBReader.getFeedMedia(testMedia11.getId()).isDownloaded());
DownloadRequester.getInstance().downloadMedia(InstrumentationRegistry.getTargetContext(),
testMedia11);
Awaitility.await()
.atMost(1000, TimeUnit.MILLISECONDS)
.until(() -> feedItemEventListener.getEvents().size() > 0);
assertTrue("After media download has completed, FeedMedia object in db should indicate so.",
DBReader.getFeedMedia(testMedia11.getId()).isDownloaded());
} catch (ConditionTimeoutException cte) {
fail("The expected FeedItemEvent (for media download complete) has not been posted. "
+ cte.getMessage());
}
});
}
private static class StubDownloaderFactory implements DownloadService.DownloaderFactory {
private final long downloadTime;
@NonNull
private final Consumer<DownloadStatus> onDownloadComplete;
StubDownloaderFactory(long downloadTime, @NonNull Consumer<DownloadStatus> onDownloadComplete) {
this.downloadTime = downloadTime;
this.onDownloadComplete = onDownloadComplete;
}
@Nullable
@Override
public Downloader create(@NonNull DownloadRequest request) {
return new StubDownloader(request, downloadTime, onDownloadComplete);
}
}
}

View File

@ -1,7 +1,7 @@
package de.test.antennapod.service.download;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import android.util.Log;
import java.io.File;

View File

@ -1,6 +1,6 @@
package de.test.antennapod.service.playback;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.util.playback.Playable;

View File

@ -1,7 +1,7 @@
package de.test.antennapod.service.playback;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.util.playback.Playable;

View File

@ -2,8 +2,8 @@ package de.test.antennapod.service.playback;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import de.test.antennapod.EspressoTestUtils;
import junit.framework.AssertionFailedError;
@ -32,7 +32,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

View File

@ -1,9 +1,15 @@
package de.test.antennapod.service.playback;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.LargeTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.LargeTest;
import org.awaitility.Awaitility;
import org.greenrobot.eventbus.EventBus;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
@ -15,14 +21,14 @@ import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceTaskManager;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
import org.greenrobot.eventbus.EventBus;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static de.test.antennapod.util.event.FeedItemEventListener.withFeedItemEventListener;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@ -123,6 +129,43 @@ public class PlaybackServiceTaskManagerTest {
pstm.shutdown();
}
@Test
public void testQueueUpdatedUponDownloadComplete() throws Exception {
final Context c = InstrumentationRegistry.getInstrumentation().getTargetContext();
{ // Setup test data
List<FeedItem> queue = writeTestQueue("a");
FeedItem item = DBReader.getFeedItem(queue.get(0).getId());
FeedMedia media = new FeedMedia(item, "http://example.com/episode.mp3", 12345, "audio/mp3");
item.setMedia(media);
DBWriter.setFeedMedia(media).get();
DBWriter.setFeedItem(item).get();
}
PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM);
final FeedItem testItem = pstm.getQueue().get(0);
assertFalse("The item should not yet be downloaded", testItem.getMedia().isDownloaded());
withFeedItemEventListener( feedItemEventListener -> {
// simulate download complete (in DownloadService.MediaHandlerThread)
FeedItem item = DBReader.getFeedItem(testItem.getId());
item.getMedia().setDownloaded(true);
item.getMedia().setFile_url("file://123");
item.setAutoDownload(false);
DBWriter.setFeedMedia(item.getMedia()).get();
DBWriter.setFeedItem(item).get();
Awaitility.await()
.atMost(1000, TimeUnit.MILLISECONDS)
.until(() -> feedItemEventListener.getEvents().size() > 0);
final FeedItem itemUpdated = pstm.getQueue().get(0);
assertTrue("media.isDownloaded() should be true - The queue in PlaybackService should be updated after download is completed",
itemUpdated.getMedia().isDownloaded());
});
pstm.shutdown();
}
@Test
public void testStartPositionSaver() throws InterruptedException {
final Context c = InstrumentationRegistry.getInstrumentation().getTargetContext();

View File

@ -10,9 +10,9 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;

View File

@ -10,9 +10,9 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;

View File

@ -5,7 +5,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.support.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.UserPreferences;

View File

@ -7,9 +7,9 @@ import java.util.Date;
import java.util.List;
import java.util.Random;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;

View File

@ -7,9 +7,9 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;

View File

@ -4,9 +4,9 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.preference.PreferenceManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import android.util.Log;
import org.awaitility.Awaitility;
@ -33,7 +33,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

View File

@ -1,20 +1,16 @@
package de.test.antennapod.ui;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.support.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.runner.AndroidJUnit4;
import com.robotium.solo.Solo;
import com.robotium.solo.Timeout;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.dialog.RatingDialog;
import de.test.antennapod.EspressoTestUtils;
import org.junit.After;
import org.junit.Before;
@ -24,11 +20,11 @@ import org.junit.runner.RunWith;
import java.io.IOException;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.contrib.ActivityResultMatchers.hasResultCode;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.contrib.ActivityResultMatchers.hasResultCode;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static de.test.antennapod.EspressoTestUtils.clickPreference;
import static de.test.antennapod.EspressoTestUtils.openNavDrawer;
import static junit.framework.TestCase.assertTrue;

View File

@ -1,21 +1,17 @@
package de.test.antennapod.ui;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.ViewInteraction;
import android.support.test.espresso.contrib.DrawerActions;
import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.support.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.ViewInteraction;
import androidx.test.espresso.contrib.DrawerActions;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.runner.AndroidJUnit4;
import android.view.View;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.dialog.RatingDialog;
import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
@ -33,15 +29,15 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.longClick;
import static android.support.test.espresso.action.ViewActions.scrollTo;
import static android.support.test.espresso.intent.Intents.intended;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.longClick;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static de.test.antennapod.EspressoTestUtils.waitForView;
import static de.test.antennapod.NthMatcher.first;
import static junit.framework.TestCase.assertTrue;

View File

@ -4,9 +4,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import android.view.View;
import android.widget.ListView;
@ -23,14 +23,13 @@ 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.storage.PodDBAdapter;
import de.test.antennapod.EspressoTestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

View File

@ -4,9 +4,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import android.view.View;
import android.widget.ListView;

View File

@ -4,9 +4,9 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.preference.PreferenceManager;
import android.support.test.filters.LargeTest;
import androidx.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import androidx.test.rule.ActivityTestRule;
import com.robotium.solo.Solo;
import com.robotium.solo.Timeout;
@ -29,12 +29,12 @@ import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static de.test.antennapod.EspressoTestUtils.clickPreference;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;

View File

@ -1,9 +1,9 @@
package de.test.antennapod.ui;
import android.content.Intent;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.intent.rule.IntentsTestRule;
import android.support.test.runner.AndroidJUnit4;
import androidx.test.espresso.Espresso;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.runner.AndroidJUnit4;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.fragment.QueueFragment;
@ -13,10 +13,10 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
/**
* User interface tests for queue fragment

View File

@ -5,9 +5,9 @@ import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import org.junit.After;

View File

@ -1,8 +1,8 @@
package de.test.antennapod.ui;
import android.content.Intent;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.VideoplayerActivity;
@ -10,10 +10,10 @@ import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
/**
* Test class for VideoplayerActivity

View File

@ -1,8 +1,8 @@
package de.test.antennapod.util;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import android.text.TextUtils;
import java.io.File;

View File

@ -1,6 +1,6 @@
package de.test.antennapod.util;
import android.support.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.util.URLChecker;
import org.junit.Test;

View File

@ -0,0 +1,46 @@
package de.test.antennapod.util.event;
import androidx.annotation.NonNull;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.List;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import io.reactivex.functions.Consumer;
/**
* Test helpers to listen {@link FeedItemEvent} and handle them accordingly
*
*/
public class FeedItemEventListener {
private final List<FeedItemEvent> events = new ArrayList<>();
/**
* Provides an listener subscribing to {@link FeedItemEvent} that the callers can use
*
* Note: it uses RxJava's version of {@link Consumer} because it allows exceptions to be thrown.
*/
public static void withFeedItemEventListener(@NonNull Consumer<FeedItemEventListener> consumer)
throws Exception {
FeedItemEventListener feedItemEventListener = new FeedItemEventListener();
try {
EventBus.getDefault().register(feedItemEventListener);
consumer.accept(feedItemEventListener);
} finally {
EventBus.getDefault().unregister(feedItemEventListener);
}
}
@Subscribe
public void onEvent(FeedItemEvent event) {
events.add(event);
}
@NonNull
public List<? extends FeedItemEvent> getEvents() {
return events;
}
}

View File

@ -2,8 +2,8 @@ package de.test.antennapod.util.playback;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

View File

@ -72,20 +72,6 @@ public class HTTPBin extends NanoHTTPD {
return servedFiles.size() - 1;
}
/**
* Removes the file with the given ID from the server.
*
* @return True if a file was removed, false otherwise
*/
public synchronized boolean removeFile(int id) {
if (id < 0) throw new IllegalArgumentException("ID < 0");
if (id >= servedFiles.size()) {
return false;
} else {
return servedFiles.remove(id) != null;
}
}
public synchronized File accessFile(int id) {
if (id < 0 || id >= servedFiles.size()) {
return null;

View File

@ -1,12 +1,11 @@
package de.test.antennapod.util.syndication;
import android.support.test.InstrumentationRegistry;
import androidx.test.InstrumentationRegistry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.util.Map;
import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;

View File

@ -1,218 +1,15 @@
package de.danoeh.antennapod.activity;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
/**
* 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) {
// no-op
}
// 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);
// }
// }
}

View File

@ -36,7 +36,7 @@
android:usesCleartextTraffic="true"
android:logo="@mipmap/ic_launcher">
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
android:resource="@drawable/ic_notification" />
android:resource="@drawable/ic_antenna" />
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/>
@ -105,17 +105,6 @@
android:value="de.danoeh.antennapod.activity.MainActivity"/>
</activity>
<activity
android:name=".activity.FeedInfoActivity"
android:label="@string/feed_info_label">
</activity>
<activity
android:name=".activity.FeedSettingsActivity"
android:windowSoftInputMode="stateHidden"
android:label="@string/feed_settings_label">
</activity>
<service
android:name=".core.service.PlayerWidgetJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
@ -150,13 +139,6 @@
android:name="android.support.PARENT_ACTIVITY"
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.ImportExportActivity"
android:label="@string/import_export">
@ -209,6 +191,13 @@
android:name=".activity.OpmlFeedChooserActivity"
android:label="@string/opml_import_label">
</activity>
<activity
android:name=".activity.BugReportActivity"
android:label="@string/bug_report_title">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
</activity>
<activity
android:name=".activity.VideoplayerActivity"
@ -350,7 +339,7 @@
<provider
android:authorities="@string/provider_authority"
android:name="android.support.v4.content.FileProvider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data

View File

@ -9,6 +9,9 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@ -32,13 +35,7 @@ public class CrashReportWriter implements Thread.UncaughtExceptionHandler {
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(path));
out.println("[ Environment ]");
out.println("Android version: " + Build.VERSION.RELEASE);
out.println("OS version: " + System.getProperty("os.version"));
out.println("AntennaPod version: " + BuildConfig.VERSION_NAME);
out.println("Model: " + Build.MODEL);
out.println("Device: " + Build.DEVICE);
out.println("Product: " + Build.PRODUCT);
out.println(getSystemInfo());
out.println();
out.println("[ StackTrace ]");
ex.printStackTrace(out);
@ -49,4 +46,15 @@ public class CrashReportWriter implements Thread.UncaughtExceptionHandler {
}
defaultHandler.uncaughtException(thread, ex);
}
public static String getSystemInfo() {
return "[ Environment ]" +
"\nAndroid version: " + Build.VERSION.RELEASE +
"\nOS version: " + System.getProperty("os.version") +
"\nAntennaPod version: " + BuildConfig.VERSION_NAME +
"\nModel: " + Build.MODEL +
"\nDevice: " + Build.DEVICE +
"\nProduct: " + Build.PRODUCT +
"\nTime: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date()) + "\n";
}
}

View File

@ -63,6 +63,8 @@ public class PodcastApp extends Application {
EventBus.builder()
.addIndex(new ApEventBusIndex())
.addIndex(new ApCoreEventBusIndex())
.logNoSubscriberMessages(false)
.sendNoSubscriberEvent(false)
.installDefaultEventBus();
}

View File

@ -1,12 +1,10 @@
package de.danoeh.antennapod.activity;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
@ -15,6 +13,7 @@ import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import de.danoeh.antennapod.core.util.IntentUtils;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
@ -57,8 +56,7 @@ public class AboutActivity extends AppCompatActivity {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("http")) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent);
IntentUtils.openInBrowser(AboutActivity.this, url);
return true;
} else {
url = url.replace("file:///android_asset/", "");

View File

@ -1,7 +1,7 @@
package de.danoeh.antennapod.activity;
import android.content.Intent;
import android.support.v4.view.ViewCompat;
import androidx.core.view.ViewCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@ -62,11 +62,13 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
}
if (controller == null) {
butPlaybackSpeed.setVisibility(View.GONE);
txtvPlaybackSpeed.setVisibility(View.GONE);
return;
}
updatePlaybackSpeedButtonText();
ViewCompat.setAlpha(butPlaybackSpeed, controller.canSetPlaybackSpeed() ? 1.0f : 0.5f);
butPlaybackSpeed.setVisibility(View.VISIBLE);
txtvPlaybackSpeed.setVisibility(View.VISIBLE);
}
@Override
@ -76,14 +78,15 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
}
if (controller == null) {
butPlaybackSpeed.setVisibility(View.GONE);
txtvPlaybackSpeed.setVisibility(View.GONE);
return;
}
float speed = 1.0f;
if(controller.canSetPlaybackSpeed()) {
speed = UserPreferences.getPlaybackSpeed(controller.getMedia());
}
String speedStr = new DecimalFormat("0.00x").format(speed);
butPlaybackSpeed.setText(speedStr);
String speedStr = new DecimalFormat("0.00").format(speed);
txtvPlaybackSpeed.setText(speedStr);
}
@Override
@ -142,6 +145,7 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
return true;
});
butPlaybackSpeed.setVisibility(View.VISIBLE);
txtvPlaybackSpeed.setVisibility(View.VISIBLE);
}
}

View File

@ -0,0 +1,55 @@
package de.danoeh.antennapod.activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.TextView;
import de.danoeh.antennapod.CrashReportWriter;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.IntentUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* Displays the 'crash report' screen
*/
public class BugReportActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayShowHomeEnabled(true);
setContentView(R.layout.bug_report);
TextView crashDetailsText = findViewById(R.id.crash_report_logs);
try {
File crashFile = CrashReportWriter.getFile();
String crashReportContent = IOUtils.toString(new FileInputStream(crashFile), Charset.forName("UTF-8"));
crashDetailsText.setText(crashReportContent);
} catch (IOException e) {
e.printStackTrace();
crashDetailsText.setText("No crash report recorded\n" + CrashReportWriter.getSystemInfo());
}
findViewById(R.id.btn_open_bug_tracker).setOnClickListener(v -> {
IntentUtils.openInBrowser(BugReportActivity.this, "https://github.com/AntennaPod/AntennaPod/issues");
});
findViewById(R.id.btn_copy_log).setOnClickListener(v -> {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(getString(R.string.bug_report_title), crashDetailsText.getText());
clipboard.setPrimaryClip(clip);
Snackbar.make(findViewById(android.R.id.content), R.string.copied_to_clipboard, Snackbar.LENGTH_SHORT).show();
});
}
}

View File

@ -49,6 +49,7 @@ public class CastplayerActivity extends MediaplayerInfoActivity {
super.setupGUI();
if (butPlaybackSpeed != null) {
butPlaybackSpeed.setVisibility(View.GONE);
txtvPlaybackSpeed.setVisibility(View.GONE);
}
// if (butCastDisconnect != null) {
// butCastDisconnect.setOnClickListener(v -> castManager.disconnect());

View File

@ -5,9 +5,9 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileObserver;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import androidx.core.app.NavUtils;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;

View File

@ -3,8 +3,8 @@ package de.danoeh.antennapod.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

View File

@ -1,225 +0,0 @@
package de.danoeh.antennapod.activity;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.graphics.LightingColorFilter;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.joanzapata.iconify.Iconify;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LangUtils;
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import io.reactivex.Maybe;
import io.reactivex.MaybeOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* Displays information about a feed.
*/
public class FeedInfoActivity extends AppCompatActivity {
public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
private static final String TAG = "FeedInfoActivity";
private Feed feed;
private ImageView imgvCover;
private TextView txtvTitle;
private TextView txtvDescription;
private TextView lblLanguage;
private TextView txtvLanguage;
private TextView lblAuthor;
private TextView txtvAuthor;
private TextView txtvUrl;
private Disposable disposable;
private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
@Override
public void onClick(View v) {
if(feed != null && feed.getDownload_url() != null) {
String url = feed.getDownload_url();
ClipData clipData = ClipData.newPlainText(url, url);
android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedInfoActivity.this
.getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(clipData);
Toast t = Toast.makeText(FeedInfoActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT);
t.show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
setContentView(R.layout.feedinfo);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1);
imgvCover = findViewById(R.id.imgvCover);
txtvTitle = findViewById(R.id.txtvTitle);
TextView txtvAuthorHeader = findViewById(R.id.txtvAuthor);
ImageView imgvBackground = findViewById(R.id.imgvBackground);
findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
// https://github.com/bumptech/glide/issues/529
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
txtvDescription = findViewById(R.id.txtvDescription);
lblLanguage = findViewById(R.id.lblLanguage);
txtvLanguage = findViewById(R.id.txtvLanguage);
lblAuthor = findViewById(R.id.lblAuthor);
txtvAuthor = findViewById(R.id.txtvDetailsAuthor);
txtvUrl = findViewById(R.id.txtvUrl);
txtvUrl.setOnClickListener(copyUrlToClipboard);
disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> {
Feed feed = DBReader.getFeed(feedId);
if (feed != null) {
emitter.onSuccess(feed);
} else {
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
feed = result;
Log.d(TAG, "Language is " + feed.getLanguage());
Log.d(TAG, "Author is " + feed.getAuthor());
Log.d(TAG, "URL is " + feed.getDownload_url());
Glide.with(FeedInfoActivity.this)
.load(feed.getImageLocation())
.apply(new RequestOptions()
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate())
.into(imgvCover);
Glide.with(FeedInfoActivity.this)
.load(feed.getImageLocation())
.apply(new RequestOptions()
.placeholder(R.color.image_readability_tint)
.error(R.color.image_readability_tint)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.transform(new FastBlurTransformation())
.dontAnimate())
.into(imgvBackground);
txtvTitle.setText(feed.getTitle());
String description = feed.getDescription();
if(description != null) {
if(Feed.TYPE_ATOM1.equals(feed.getType())) {
HtmlToPlainText formatter = new HtmlToPlainText();
Document feedDescription = Jsoup.parse(feed.getDescription());
description = StringUtils.trim(formatter.getPlainText(feedDescription));
}
} else {
description = "";
}
txtvDescription.setText(description);
if (!TextUtils.isEmpty(feed.getAuthor())) {
txtvAuthor.setText(feed.getAuthor());
txtvAuthorHeader.setText(feed.getAuthor());
} else {
lblAuthor.setVisibility(View.GONE);
txtvAuthor.setVisibility(View.GONE);
}
if (!TextUtils.isEmpty(feed.getLanguage())) {
txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage()));
} else {
lblLanguage.setVisibility(View.GONE);
txtvLanguage.setVisibility(View.GONE);
}
txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}");
Iconify.addIcons(txtvUrl);
supportInvalidateOptionsMenu();
}, error -> {
Log.d(TAG, Log.getStackTraceString(error));
finish();
}, () -> {
Log.e(TAG, "Activity was started with invalid arguments");
finish();
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (disposable != null) {
disposable.dispose();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.feedinfo, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null);
menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null &&
IntentUtils.isCallable(this, new Intent(Intent.ACTION_VIEW, Uri.parse(feed.getLink()))));
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
try {
return FeedMenuHandler.onOptionsItemClicked(this, item, feed);
} catch (DownloadRequestException e) {
e.printStackTrace();
DownloadRequestErrorDialogCreator.newRequestErrorDialog(this,
e.getMessage());
}
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -1,130 +0,0 @@
package de.danoeh.antennapod.activity;
import android.arch.lifecycle.ViewModelProviders;
import android.graphics.LightingColorFilter;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.fragment.FeedSettingsFragment;
import de.danoeh.antennapod.viewmodel.FeedSettingsViewModel;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* Displays information about a feed.
*/
public class FeedSettingsActivity extends AppCompatActivity {
public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
private static final String TAG = "FeedSettingsActivity";
private Feed feed;
private Disposable disposable;
private ImageView imgvCover;
private TextView txtvTitle;
private ImageView imgvBackground;
private TextView txtvAuthorHeader;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
setContentView(R.layout.feedsettings);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
imgvCover = findViewById(R.id.imgvCover);
txtvTitle = findViewById(R.id.txtvTitle);
txtvAuthorHeader = findViewById(R.id.txtvAuthor);
imgvBackground = findViewById(R.id.imgvBackground);
findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
// https://github.com/bumptech/glide/issues/529
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1);
disposable = ViewModelProviders.of(this).get(FeedSettingsViewModel.class).getFeed(feedId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
feed = result;
showFragment();
showHeader();
}, error -> {
Log.d(TAG, Log.getStackTraceString(error));
finish();
}, () -> {
Log.e(TAG, "Activity was started with invalid arguments");
finish();
});
}
private void showFragment() {
FeedSettingsFragment fragment = new FeedSettingsFragment();
fragment.setArguments(getIntent().getExtras());
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.settings_fragment_container, fragment);
fragmentTransaction.commit();
}
private void showHeader() {
txtvTitle.setText(feed.getTitle());
if (!TextUtils.isEmpty(feed.getAuthor())) {
txtvAuthorHeader.setText(feed.getAuthor());
}
Glide.with(FeedSettingsActivity.this)
.load(feed.getImageLocation())
.apply(new RequestOptions()
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate())
.into(imgvCover);
Glide.with(FeedSettingsActivity.this)
.load(feed.getImageLocation())
.apply(new RequestOptions()
.placeholder(R.color.image_readability_tint)
.error(R.color.image_readability_tint)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.transform(new FastBlurTransformation())
.dontAnimate())
.into(imgvBackground);
}
@Override
public void onDestroy() {
super.onDestroy();
if (disposable != null) {
disposable.dispose();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -7,10 +7,10 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;

View File

@ -2,6 +2,7 @@ package de.danoeh.antennapod.activity;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@ -10,15 +11,16 @@ import android.database.DataSetObserver;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.VisibleForTesting;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
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.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.google.android.material.snackbar.Snackbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
@ -32,9 +34,11 @@ import android.widget.Toast;
import com.bumptech.glide.Glide;
import de.danoeh.antennapod.preferences.PreferenceUpgrader;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
@ -43,7 +47,6 @@ 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.event.MessageEvent;
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;
@ -66,14 +69,13 @@ import de.danoeh.antennapod.fragment.FeedItemlistFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import de.danoeh.antennapod.fragment.TransitionEffect;
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
import de.danoeh.antennapod.preferences.PreferenceUpgrader;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/**
* The activity that is shown when the user launches the app.
@ -93,7 +95,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
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";
private static final String EXTRA_FEED_ID = "fragment_feed_id";
private static final String SAVE_BACKSTACK_COUNT = "backstackCount";
private static final String SAVE_TITLE = "title";
@ -127,6 +129,14 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
private long lastBackButtonPressTime = 0;
@NonNull
public static Intent getIntentToOpenFeed(@NonNull Context context, long feedId) {
Intent intent = new Intent(context.getApplicationContext(), MainActivity.class);
intent.putExtra(MainActivity.EXTRA_FEED_ID, feedId);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return intent;
}
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getNoTitleTheme());
@ -240,7 +250,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(PREF_IS_FIRST_LAUNCH, false);
edit.commit();
edit.apply();
}
}
@ -368,15 +378,34 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
}
public void loadChildFragment(Fragment fragment) {
public void loadChildFragment(Fragment fragment, TransitionEffect transition) {
Validate.notNull(fragment);
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.replace(R.id.main_view, fragment, "main")
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch (transition) {
case FADE:
transaction.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
break;
case FLIP:
transaction.setCustomAnimations(
R.anim.card_flip_left_in,
R.anim.card_flip_left_out,
R.anim.card_flip_right_in,
R.anim.card_flip_right_out);
break;
}
transaction
.hide(getSupportFragmentManager().findFragmentByTag("main"))
.add(R.id.main_view, fragment, "main")
.addToBackStack(null)
.commit();
}
public void loadChildFragment(Fragment fragment) {
loadChildFragment(fragment, TransitionEffect.NONE);
}
public void dismissChildFragment() {
getSupportFragmentManager().popBackStack();
}
@ -777,25 +806,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
loadData();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(ProgressEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
switch(event.action) {
case START:
pd = new ProgressDialog(this);
pd.setMessage(event.message);
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.show();
break;
case END:
if(pd != null) {
pd.dismiss();
}
break;
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(MessageEvent event) {
Log.d(TAG, "onEvent(" + event + ")");

View File

@ -9,14 +9,13 @@ import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AlertDialog;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@ -34,6 +33,7 @@ import com.joanzapata.iconify.IconDrawable;
import com.joanzapata.iconify.fonts.FontAwesomeIcons;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
@ -63,6 +63,9 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import static de.danoeh.antennapod.core.feed.FeedPreferences.SPEED_USE_GLOBAL;
@ -196,6 +199,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
};
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(PlaybackPositionEvent event) {
onPositionObserverUpdate();
}
private static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
return activity.txtvFF;
}
@ -276,6 +284,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
controller.init();
loadMediaInfo();
onPositionObserverUpdate();
EventBus.getDefault().register(this);
}
@Override
@ -288,6 +297,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
if (disposable != null) {
disposable.dispose();
}
EventBus.getDefault().unregister(this);
super.onStop();
}
@ -324,6 +334,8 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
Playable media = controller.getMedia();
boolean isFeedMedia = media != null && (media instanceof FeedMedia);
menu.findItem(R.id.open_feed_item).setVisible(isFeedMedia); // FeedMedia implies it belongs to a Feed
boolean hasWebsiteLink = ( getWebsiteLinkWithFallback(media) != null );
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink);
@ -391,29 +403,24 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return true;
} else {
if (media != null) {
final @Nullable FeedItem feedItem = getFeedItem(media); // some options option requires FeedItem
switch (item.getItemId()) {
case R.id.add_to_favorites_item:
if(media instanceof FeedMedia) {
FeedItem feedItem = ((FeedMedia)media).getItem();
if(feedItem != null) {
DBWriter.addFavoriteItem(feedItem);
isFavorite = true;
invalidateOptionsMenu();
Toast.makeText(this, R.string.added_to_favorites, Toast.LENGTH_SHORT)
.show();
}
if (feedItem != null) {
DBWriter.addFavoriteItem(feedItem);
isFavorite = true;
invalidateOptionsMenu();
Toast.makeText(this, R.string.added_to_favorites, Toast.LENGTH_SHORT)
.show();
}
break;
case R.id.remove_from_favorites_item:
if(media instanceof FeedMedia) {
FeedItem feedItem = ((FeedMedia)media).getItem();
if(feedItem != null) {
DBWriter.removeFavoriteItem(feedItem);
isFavorite = false;
invalidateOptionsMenu();
Toast.makeText(this, R.string.removed_from_favorites, Toast.LENGTH_SHORT)
.show();
}
if (feedItem != null) {
DBWriter.removeFavoriteItem(feedItem);
isFavorite = false;
invalidateOptionsMenu();
Toast.makeText(this, R.string.removed_from_favorites, Toast.LENGTH_SHORT)
.show();
}
break;
case R.id.disable_sleeptimer_item:
@ -450,28 +457,33 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
PlaybackControlsDialog dialog = PlaybackControlsDialog.newInstance(isPlayingVideo);
dialog.show(getSupportFragmentManager(), "playback_controls");
break;
case R.id.open_feed_item:
if (feedItem != null) {
Intent intent = MainActivity.getIntentToOpenFeed(this, feedItem.getFeedId());
startActivity(intent);
}
break;
case R.id.visit_website_item:
Uri uri = Uri.parse(getWebsiteLinkWithFallback(media));
startActivity(new Intent(Intent.ACTION_VIEW, uri));
IntentUtils.openInBrowser(MediaplayerActivity.this, getWebsiteLinkWithFallback(media));
break;
case R.id.share_link_item:
if (media instanceof FeedMedia) {
ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem());
if (feedItem != null) {
ShareUtils.shareFeedItemLink(this, feedItem);
}
break;
case R.id.share_download_url_item:
if (media instanceof FeedMedia) {
ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem());
if (feedItem != null) {
ShareUtils.shareFeedItemDownloadLink(this, feedItem);
}
break;
case R.id.share_link_with_position_item:
if (media instanceof FeedMedia) {
ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem(), true);
if (feedItem != null) {
ShareUtils.shareFeedItemLink(this, feedItem, true);
}
break;
case R.id.share_download_url_with_position_item:
if (media instanceof FeedMedia) {
ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true);
if (feedItem != null) {
ShareUtils.shareFeedItemDownloadLink(this, feedItem, true);
}
break;
case R.id.share_file:
@ -637,7 +649,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
}
static public void showSkipPreference(Activity activity, SkipDirection direction) {
public static void showSkipPreference(Activity activity, SkipDirection direction) {
int checked = 0;
int skipSecs = direction.getPrefSkipSeconds();
final int[] values = activity.getResources().getIntArray(R.array.seek_delta_values);
@ -815,11 +827,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
private void checkFavorite() {
Playable playable = controller.getMedia();
if (!(playable instanceof FeedMedia)) {
return;
}
FeedItem feedItem = ((FeedMedia) playable).getItem();
FeedItem feedItem = getFeedItem(controller.getMedia());
if (feedItem == null) {
return;
}
@ -874,4 +882,13 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
}
}
@Nullable
private static FeedItem getFeedItem(@Nullable Playable playable) {
if ((playable != null) && (playable instanceof FeedMedia)) {
return ((FeedMedia)playable).getItem();
} else {
return null;
}
}
}

View File

@ -7,15 +7,15 @@ import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.Snackbar;
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 com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.snackbar.Snackbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
@ -23,9 +23,9 @@ 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.TextView;
import android.widget.Toast;
import com.viewpagerindicator.CirclePageIndicator;
@ -63,7 +63,6 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@ -92,7 +91,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
NavListAdapter.SUBSCRIPTION_LIST_TAG
};
Button butPlaybackSpeed;
ImageButton butPlaybackSpeed;
TextView txtvPlaybackSpeed;
ImageButton butCastDisconnect;
private DrawerLayout drawerLayout;
private NavListAdapter navAdapter;
@ -120,7 +120,6 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
disposable.dispose();
}
EventDistributor.getInstance().unregister(contentUpdate);
EventBus.getDefault().unregister(this);
saveCurrentFragment();
}
@ -173,7 +172,6 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
protected void onStart() {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().register(this);
loadData();
}
@ -258,6 +256,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
});
butPlaybackSpeed = findViewById(R.id.butPlaybackSpeed);
txtvPlaybackSpeed = findViewById(R.id.txtvPlaybackSpeed);
butCastDisconnect = findViewById(R.id.butCastDisconnect);
pager = findViewById(R.id.pager);

View File

@ -7,12 +7,12 @@ import android.content.Intent;
import android.graphics.LightingColorFilter;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import androidx.core.app.NavUtils;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@ -32,7 +32,6 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import org.apache.commons.lang3.StringUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@ -55,6 +54,7 @@ import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
@ -442,11 +442,9 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
subscribeButton.setOnClickListener(v -> {
if(feedInFeedlist(feed)) {
Intent intent = new Intent(OnlineFeedViewActivity.this, MainActivity.class);
// feed.getId() is always 0, we have to retrieve the id from the feed list from
// the database
intent.putExtra(MainActivity.EXTRA_FEED_ID, getFeedId(feed));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent intent = MainActivity.getIntentToOpenFeed(this, getFeedId(feed));
startActivity(intent);
} else {
Feed f = new Feed(selectedDownloadUrl, null, feed.getTitle());

View File

@ -2,7 +2,7 @@ package de.danoeh.antennapod.activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import android.util.SparseBooleanArray;
import android.view.Menu;
import android.view.MenuInflater;

View File

@ -5,9 +5,9 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import com.afollestad.materialdialogs.MaterialDialog;

View File

@ -1,9 +1,9 @@
package de.danoeh.antennapod.activity;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.preference.PreferenceFragmentCompat;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceFragmentCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;

View File

@ -5,9 +5,9 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.AppCompatActivity;
import androidx.annotation.Nullable;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.ProgressBar;
import de.danoeh.antennapod.R;

View File

@ -9,9 +9,9 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Button;

View File

@ -6,8 +6,8 @@ import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.WindowCompat;
import android.support.v7.app.ActionBar;
import androidx.core.view.WindowCompat;
import androidx.appcompat.app.ActionBar;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

View File

@ -2,11 +2,10 @@ package de.danoeh.antennapod.activity.gpoddernet;
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.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;

View File

@ -1,10 +1,11 @@
package de.danoeh.antennapod.adapter;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.ItemTouchHelper;
import android.text.Layout;
import android.util.Log;
import android.view.ContextMenu;
@ -23,10 +24,12 @@ import android.widget.TextView;
import com.joanzapata.iconify.Iconify;
import java.lang.ref.WeakReference;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.storage.DownloadRequester;
@ -50,6 +53,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
private final boolean showOnlyNewEpisodes;
private FeedItem selectedItem;
private Holder currentlyPlayingItem = null;
private final int playingBackGroundColor;
private final int normalBackGroundColor;
@ -165,8 +169,9 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.progress.setVisibility(View.INVISIBLE);
}
if(media.isCurrentlyPlaying()) {
if (media.isCurrentlyPlaying()) {
holder.container.setBackgroundColor(playingBackGroundColor);
currentlyPlayingItem = holder;
} else {
holder.container.setBackgroundColor(normalBackGroundColor);
}
@ -196,6 +201,22 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
.load();
}
@Override
public void onBindViewHolder(@NonNull Holder holder, int pos, List<Object> payload) {
onBindViewHolder(holder, pos);
if (holder == currentlyPlayingItem && payload.size() == 1 && payload.get(0) instanceof PlaybackPositionEvent) {
PlaybackPositionEvent event = (PlaybackPositionEvent) payload.get(0);
holder.progress.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
}
}
public void notifyCurrentlyPlayingItemChanged(PlaybackPositionEvent event) {
if (currentlyPlayingItem != null && currentlyPlayingItem.getAdapterPosition() != RecyclerView.NO_POSITION) {
notifyItemChanged(currentlyPlayingItem.getAdapterPosition(), event);
}
}
@Nullable
public FeedItem getSelectedItem() {
return selectedItem;
@ -262,7 +283,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
FeedItem item = itemAccess.getItem(getAdapterPosition());
MenuInflater inflater = mainActivityRef.get().getMenuInflater();
inflater.inflate(R.menu.allepisodes_context, menu);
inflater.inflate(R.menu.feeditemlist_context, menu);
if (item != null) {
menu.setHeaderTitle(item.getTitle());
@ -277,9 +298,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
item1.setVisible(visible);
}
};
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
contextMenuInterface.setItemVisibility(R.id.remove_new_flag_item, item.isNew());
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item);
}
}

View File

@ -1,8 +1,8 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;

View File

@ -1,9 +1,8 @@
package de.danoeh.antennapod.adapter;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

View File

@ -2,9 +2,9 @@ package de.danoeh.antennapod.adapter;
import android.app.Dialog;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@ -2,7 +2,7 @@ package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import androidx.core.content.ContextCompat;
import android.text.Layout;
import android.text.format.DateUtils;
import android.util.Log;

View File

@ -3,7 +3,7 @@ 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 androidx.core.content.ContextCompat;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
@ -13,15 +13,18 @@ import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.ThemeUtils;
@ -39,6 +42,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
private final int playingBackGroundColor;
private final int normalBackGroundColor;
private int currentlyPlayingItem = -1;
public FeedItemlistAdapter(Context context,
ItemAccess itemAccess,
boolean showFeedtitle,
@ -176,8 +181,9 @@ public class FeedItemlistAdapter extends BaseAdapter {
}
typeDrawables.recycle();
if(media.isCurrentlyPlaying()) {
if (media.isCurrentlyPlaying()) {
holder.container.setBackgroundColor(playingBackGroundColor);
currentlyPlayingItem = position;
} else {
holder.container.setBackgroundColor(normalBackGroundColor);
}
@ -195,6 +201,20 @@ public class FeedItemlistAdapter extends BaseAdapter {
return convertView;
}
public void notifyCurrentlyPlayingItemChanged(PlaybackPositionEvent event, ListView listView) {
if (currentlyPlayingItem != -1 && currentlyPlayingItem < getCount()) {
View view = listView.getChildAt(currentlyPlayingItem
- listView.getFirstVisiblePosition() + listView.getHeaderViewsCount());
if (view == null) {
return;
}
Holder holder = (Holder) view.getTag();
holder.episodeProgress.setVisibility(View.VISIBLE);
holder.episodeProgress.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
holder.lenSize.setText(Converter.getDurationStringLong(event.getDuration() - event.getPosition()));
}
}
static class Holder {
LinearLayout container;
TextView title;

View File

@ -1,6 +1,7 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -51,6 +52,17 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
.replaceAll("\\s+", " ")
.trim();
holder.description.setText(description);
final int MAX_LINES_COLLAPSED = 3;
holder.description.setMaxLines(MAX_LINES_COLLAPSED);
holder.description.setOnClickListener(v -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& holder.description.getMaxLines() > MAX_LINES_COLLAPSED) {
holder.description.setMaxLines(MAX_LINES_COLLAPSED);
} else {
holder.description.setMaxLines(2000);
}
});
}
return convertView;
}

View File

@ -7,7 +7,7 @@ import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceManager;
import android.support.v7.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;

View File

@ -1,12 +1,12 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.view.MotionEventCompat;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.ItemTouchHelper;
import android.text.Layout;
import android.text.TextUtils;
import android.util.Log;
@ -25,9 +25,11 @@ import android.widget.TextView;
import com.joanzapata.iconify.Iconify;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import org.apache.commons.lang3.ArrayUtils;
import java.lang.ref.WeakReference;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
@ -58,6 +60,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
private boolean locked;
private FeedItem selectedItem;
private ViewHolder currentlyPlayingItem = null;
private final int playingBackGroundColor;
private final int normalBackGroundColor;
@ -94,6 +97,18 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
});
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int pos, List<Object> payload) {
onBindViewHolder(holder, pos);
if (holder == currentlyPlayingItem && payload.size() == 1 && payload.get(0) instanceof PlaybackPositionEvent) {
PlaybackPositionEvent event = (PlaybackPositionEvent) payload.get(0);
holder.progressBar.setProgress((int) (100.0 * event.getPosition() / event.getDuration()));
holder.progressLeft.setText(Converter.getDurationStringLong(event.getPosition()));
holder.progressRight.setText(Converter.getDurationStringLong(event.getDuration()));
}
}
@Nullable
public FeedItem getSelectedItem() {
return selectedItem;
@ -109,6 +124,12 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
return itemAccess.getCount();
}
public void notifyCurrentlyPlayingItemChanged(PlaybackPositionEvent event) {
if (currentlyPlayingItem != null && currentlyPlayingItem.getAdapterPosition() != RecyclerView.NO_POSITION) {
notifyItemChanged(currentlyPlayingItem.getAdapterPosition(), event);
}
}
public class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener,
View.OnCreateContextMenuListener,
@ -169,7 +190,8 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
FeedItem item = itemAccess.getItem(getAdapterPosition());
MenuInflater inflater = mainActivity.get().getMenuInflater();
inflater.inflate(R.menu.queue_context, menu);
inflater.inflate(R.menu.queue_context, menu); // queue-specific menu items
inflater.inflate(R.menu.feeditemlist_context, menu); // generic menu items for item feeds
if (item != null) {
menu.setHeaderTitle(item.getTitle());
@ -184,7 +206,18 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
item1.setVisible(visible);
}
};
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, itemAccess.getQueueIds());
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item,
R.id.skip_episode_item); // Skip Episode is not useful in Queue, so hide it.
// Queue-specific menu preparation
final boolean keepSorted = UserPreferences.isQueueKeepSorted();
final LongList queueAccess = itemAccess.getQueueIds();
if (queueAccess.size() == 0 || queueAccess.get(0) == item.getId() || keepSorted) {
contextMenuInterface.setItemVisibility(R.id.move_to_top_item, false);
}
if (queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == item.getId() || keepSorted) {
contextMenuInterface.setItemVisibility(R.id.move_to_bottom_item, false);
}
}
@Override
@ -276,6 +309,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
if(media.isCurrentlyPlaying()) {
container.setBackgroundColor(playingBackGroundColor);
currentlyPlayingItem = this;
} else {
container.setBackgroundColor(normalBackGroundColor);
}

View File

@ -1,31 +1,30 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;
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 java.util.ArrayList;
import java.util.List;
import com.bumptech.glide.request.RequestOptions;
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;
import de.danoeh.antennapod.view.PieChartView;
/**
* Adapter for the statistics list
*/
public class StatisticsListAdapter extends BaseAdapter {
public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_FEED = 1;
private final Context context;
private List<DBReader.StatisticsItem> feedTime = new ArrayList<>();
private DBReader.StatisticsData statisticsData;
private boolean countAll = true;
public StatisticsListAdapter(Context context) {
@ -37,66 +36,102 @@ public class StatisticsListAdapter extends BaseAdapter {
}
@Override
public int getCount() {
return feedTime.size();
public int getItemCount() {
return statisticsData.feedTime.size() + 1;
}
@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 = convertView.findViewById(R.id.imgvCover);
holder.title = convertView.findViewById(R.id.txtvTitle);
holder.time = convertView.findViewById(R.id.txtvTime);
convertView.setTag(holder);
} else {
holder = (StatisticsHolder) convertView.getTag();
if (position == 0) {
return null;
}
Glide.with(context)
.load(feed.getImageLocation())
.apply(new RequestOptions()
.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,
countAll ? feedTime.get(position).timePlayedCountAll
: feedTime.get(position).timePlayed));
return convertView;
return statisticsData.feedTime.get(position - 1);
}
public void update(List<DBReader.StatisticsItem> feedTime) {
this.feedTime = feedTime;
@Override
public int getItemViewType(int position) {
return position == 0 ? TYPE_HEADER : TYPE_FEED;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
if (viewType == TYPE_HEADER) {
return new HeaderHolder(inflater.inflate(R.layout.statistics_listitem_total_time, parent, false));
}
return new StatisticsHolder(inflater.inflate(R.layout.statistics_listitem, parent, false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder h, int position) {
if (getItemViewType(position) == TYPE_HEADER) {
HeaderHolder holder = (HeaderHolder) h;
long time = countAll ? statisticsData.totalTimeCountAll : statisticsData.totalTime;
holder.totalTime.setText(Converter.shortLocalizedDuration(context, time));
float[] dataValues = new float[statisticsData.feedTime.size()];
for (int i = 0; i < statisticsData.feedTime.size(); i++) {
DBReader.StatisticsItem item = statisticsData.feedTime.get(i);
dataValues[i] = countAll ? item.timePlayedCountAll : item.timePlayed;
}
holder.pieChart.setData(dataValues);
} else {
StatisticsHolder holder = (StatisticsHolder) h;
DBReader.StatisticsItem statsItem = statisticsData.feedTime.get(position - 1);
Glide.with(context)
.load(statsItem.feed.getImageLocation())
.apply(new RequestOptions()
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate())
.into(holder.image);
holder.title.setText(statsItem.feed.getTitle());
long time = countAll ? statsItem.timePlayedCountAll : statsItem.timePlayed;
holder.time.setText(Converter.shortLocalizedDuration(context, time));
holder.itemView.setOnClickListener(v -> {
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle(statsItem.feed.getTitle());
dialog.setMessage(context.getString(R.string.statistics_details_dialog,
countAll ? statsItem.episodesStartedIncludingMarked : statsItem.episodesStarted,
statsItem.episodes, Converter.shortLocalizedDuration(context,
countAll ? statsItem.timePlayedCountAll : statsItem.timePlayed),
Converter.shortLocalizedDuration(context, statsItem.time)));
dialog.setPositiveButton(android.R.string.ok, null);
dialog.show();
});
}
}
public void update(DBReader.StatisticsData statistics) {
this.statisticsData = statistics;
notifyDataSetChanged();
}
static class StatisticsHolder {
static class HeaderHolder extends RecyclerView.ViewHolder {
TextView totalTime;
PieChartView pieChart;
HeaderHolder(View itemView) {
super(itemView);
totalTime = itemView.findViewById(R.id.total_time);
pieChart = itemView.findViewById(R.id.pie_chart);
}
}
static class StatisticsHolder extends RecyclerView.ViewHolder {
ImageView image;
TextView title;
TextView time;
StatisticsHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imgvCover);
title = itemView.findViewById(R.id.txtvTitle);
time = itemView.findViewById(R.id.txtvTime);
}
}
}

View File

@ -1,7 +1,7 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@ -1,8 +1,8 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import androidx.annotation.AttrRes;
import androidx.annotation.StringRes;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;

View File

@ -1,8 +1,8 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import androidx.annotation.AttrRes;
import androidx.annotation.StringRes;
import android.widget.Toast;
import de.danoeh.antennapod.R;

View File

@ -1,9 +1,9 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import android.widget.Toast;
import de.danoeh.antennapod.R;

View File

@ -2,9 +2,9 @@ package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import android.view.View;
import android.widget.ImageButton;
@ -20,12 +20,12 @@ public abstract class ItemActionButton {
}
@StringRes
abstract public int getLabel();
public abstract int getLabel();
@AttrRes
abstract public int getDrawable();
public abstract int getDrawable();
abstract public void onClick(Context context);
public abstract void onClick(Context context);
public int getVisibility() {
return View.VISIBLE;

View File

@ -1,8 +1,8 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import androidx.annotation.AttrRes;
import androidx.annotation.StringRes;
import android.view.View;
import de.danoeh.antennapod.R;

View File

@ -1,8 +1,8 @@
package de.danoeh.antennapod.adapter.actionbutton;
import android.content.Context;
import android.support.annotation.AttrRes;
import android.support.annotation.StringRes;
import androidx.annotation.AttrRes;
import androidx.annotation.StringRes;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;

View File

@ -1,7 +1,7 @@
package de.danoeh.antennapod.adapter.itunes;
import android.content.Context;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

View File

@ -0,0 +1,72 @@
package de.danoeh.antennapod.asynctask;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import de.danoeh.antennapod.core.export.ExportWriter;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.LangUtils;
import io.reactivex.Observable;
/**
* Writes an OPML file into the user selected export directory in the background.
*/
public class DocumentFileExportWorker {
private final @NonNull ExportWriter exportWriter;
private @NonNull Context context;
private @NonNull Uri outputFileUri;
public DocumentFileExportWorker(@NonNull ExportWriter exportWriter, @NonNull Context context, @NonNull Uri outputFileUri) {
this.exportWriter = exportWriter;
this.context = context;
this.outputFileUri = outputFileUri;
}
public Observable<DocumentFile> exportObservable() {
DocumentFile output = DocumentFile.fromSingleUri(context, outputFileUri);
return Observable.create(subscriber -> {
OutputStream outputStream = null;
OutputStreamWriter writer = null;
try {
Uri uri = output.getUri();
if (uri == null) {
throw new FileNotFoundException("Export file not found.");
}
outputStream = context.getContentResolver().openOutputStream(uri);
if (outputStream == null) {
throw new IOException();
}
writer = new OutputStreamWriter(outputStream, LangUtils.UTF_8);
exportWriter.writeDocument(DBReader.getFeedList(), writer);
subscriber.onNext(output);
} catch (IOException e) {
subscriber.onError(e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
subscriber.onError(e);
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
subscriber.onError(e);
}
}
subscriber.onComplete();
}
});
}
}

View File

@ -1,6 +1,6 @@
package de.danoeh.antennapod.asynctask;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import android.util.Log;
import java.io.File;

View File

@ -3,7 +3,7 @@ package de.danoeh.antennapod.asynctask;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.util.Log;
import org.xmlpull.v1.XmlPullParserException;

View File

@ -35,6 +35,6 @@ public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks {
@Override
public int getNotificationIconResource(Context context) {
return R.drawable.ic_stat_antenna_default;
return R.drawable.ic_antenna;
}
}

View File

@ -9,7 +9,7 @@ import de.danoeh.antennapod.adapter.DataFolderAdapter;
public class ChooseDataFolderDialog {
public static abstract class RunnableWithString implements Runnable {
public abstract static class RunnableWithString implements Runnable {
public RunnableWithString() {
super();
}

View File

@ -4,16 +4,16 @@ import android.app.AlertDialog;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.PluralsRes;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.util.ArrayMap;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
import com.google.android.material.snackbar.Snackbar;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.collection.ArrayMap;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;

View File

@ -1,7 +1,7 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
import android.support.v7.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.text.TextUtils;
import java.util.Arrays;

View File

@ -1,7 +1,7 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
import android.support.v7.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.InputType;
import android.view.View;

View File

@ -2,8 +2,8 @@ package de.danoeh.antennapod.dialog;
import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.SeekBar;

View File

@ -4,7 +4,7 @@ import android.app.Dialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import androidx.core.content.ContextCompat;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;

View File

@ -2,11 +2,9 @@ package de.danoeh.antennapod.dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import android.util.Log;
import com.afollestad.materialdialogs.MaterialDialog;
@ -15,6 +13,7 @@ import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.util.IntentUtils;
public class RatingDialog {
@ -59,14 +58,10 @@ public class RatingDialog {
private static void rateNow() {
Context context = mContext.get();
if(context == null) {
if (context == null) {
return;
}
final String appPackage = "de.danoeh.antennapod";
final Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=" + appPackage);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
IntentUtils.openInBrowser(context, "https://play.google.com/store/apps/details?id=de.danoeh.antennapod");
saveRated();
}

View File

@ -5,7 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.v7.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.util.Log;
import android.view.View;

View File

@ -1,6 +1,6 @@
package de.danoeh.antennapod.discovery;
import android.support.annotation.Nullable;
import androidx.annotation.Nullable;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetPodcast;
import de.mfietz.fyydlin.SearchHit;
import org.json.JSONArray;

View File

@ -2,20 +2,15 @@ package de.danoeh.antennapod.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import androidx.fragment.app.Fragment;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;

View File

@ -1,9 +1,9 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;

View File

@ -1,7 +1,7 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import androidx.fragment.app.ListFragment;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
@ -87,11 +87,10 @@ public class ChaptersFragment extends ListFragment {
controller = null;
}
private void scrollTo(int position) {
getListView().setSelection(position);
}
private int getCurrentChapter(Playable media) {
if (media == null || media.getChapters() == null || media.getChapters().size() == 0 || controller == null) {
return -1;
}
int currentPosition = controller.getPosition();
List<Chapter> chapters = media.getChapters();
@ -126,8 +125,10 @@ public class ChaptersFragment extends ListFragment {
if (adapter != null) {
adapter.setMedia(media);
adapter.notifyDataSetChanged();
if (media != null && media.getChapters() != null && media.getChapters().size() != 0) {
scrollTo(getCurrentChapter(media));
int positionOfCurrentChapter = getCurrentChapter(media);
if (positionOfCurrentChapter != -1) {
getListView().setSelection(positionOfCurrentChapter);
}
}
}

View File

@ -2,9 +2,9 @@ package de.danoeh.antennapod.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import androidx.fragment.app.Fragment;
import androidx.core.view.MenuItemCompat;
import androidx.appcompat.widget.SearchView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;

View File

@ -1,8 +1,8 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ListFragment;
import androidx.annotation.NonNull;
import androidx.fragment.app.ListFragment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;

View File

@ -1,8 +1,8 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

Some files were not shown because too many files have changed in this diff Show More