Merge branch 'develop'
This commit is contained in:
commit
12c5819380
36
.circleci/config.yml
Normal file
36
.circleci/config.yml
Normal file
@ -0,0 +1,36 @@
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/android:api-26-alpha
|
||||
|
||||
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:
|
||||
command: ./gradlew assembleDebug :core:testPlayDebugUnitTest -PdisablePreDex
|
||||
no_output_timeout: 1800
|
||||
|
||||
- store_artifacts:
|
||||
path: app/build/outputs/apk
|
||||
destination: apks
|
||||
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/.android
|
||||
- ~/.gradle
|
||||
- ~/android
|
||||
key: v1-android-{{ checksum "build.gradle" }}
|
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
33
.project
33
.project
@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>AntennaPod</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
17
.travis.yml
17
.travis.yml
@ -1,17 +0,0 @@
|
||||
language: android
|
||||
jdk: oraclejdk7
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- ANDROID_SDKS=android-19,sysimg-19 ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
|
||||
before_install:
|
||||
- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI
|
||||
- emulator -avd test -no-skin -no-audio -no-window &
|
||||
- cp src/de/danoeh/antennapod/util/flattr/FlattrConfig.java.example src/de/danoeh/antennapod/util/flattr/FlattrConfig.java
|
||||
|
||||
before_script:
|
||||
- chmod -R 777 ./ci/wait_for_emulator.sh
|
||||
- ./ci/wait_for_emulator.sh
|
||||
|
||||
script:
|
||||
- gradle connectedAndroidTest
|
@ -7,6 +7,7 @@ source_lang = en
|
||||
trans.ast_ES = core/src/main/res/values-b+ast/strings.xml
|
||||
trans.ar = core/src/main/res/values-ar/strings.xml
|
||||
trans.az = core/src/main/res/values-az/strings.xml
|
||||
trans.bg = core/src/main/res/values-bg/strings.xml
|
||||
trans.ca = core/src/main/res/values-ca/strings.xml
|
||||
trans.ca_ES = core/src/main/res/values-ca-rES/strings.xml
|
||||
trans.cs_CZ = core/src/main/res/values-cs-rCZ/strings.xml
|
||||
@ -32,6 +33,7 @@ trans.kn_IN = core/src/main/res/values-kn-rIN/strings.xml
|
||||
trans.ko = core/src/main/res/values-ko/strings.xml
|
||||
trans.ko_KR = core/src/main/res/values-ko-rKR/strings.xml
|
||||
trans.lt = core/src/main/res/values-lt/strings.xml
|
||||
trans.mk = core/src/main/res/values-mk/strings.xml
|
||||
trans.nb = core/src/main/res/values-nb/strings.xml
|
||||
trans.no = core/src/main/res/values-no/strings.xml
|
||||
trans.nl = core/src/main/res/values-nl/strings.xml
|
||||
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -1,6 +1,32 @@
|
||||
Change Log
|
||||
==========
|
||||
|
||||
Version 1.7.0
|
||||
-------------
|
||||
|
||||
* NEW ExoPlayer (experimental)
|
||||
* Fix for Bluetooth Forward (Oreo)
|
||||
* Preference redesign + search
|
||||
* Notification improvements
|
||||
* Different screens for feed info and settings
|
||||
* Sort Queue with Random or Smart Shuffle
|
||||
* True Black Theme for AMOLED
|
||||
* Improvements to feed parsing
|
||||
* Fix for app being killed by Android Oreo
|
||||
|
||||
Version 1.6.5
|
||||
-------------
|
||||
|
||||
* Fix database corruption
|
||||
* Improvements to Feed parsing
|
||||
|
||||
Version 1.6.4
|
||||
-------------
|
||||
|
||||
* Fixes issues on Android Oreo
|
||||
* Avoids duplicate chapters
|
||||
* Experimental: Database import & export
|
||||
|
||||
Version 1.6.3
|
||||
-------------
|
||||
|
||||
|
@ -5,7 +5,7 @@ This is the official repository of AntennaPod, the easy-to-use, flexible and ope
|
||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
|
||||
alt="Get it on Google Play"
|
||||
height="90">](https://play.google.com/store/apps/details?id=de.danoeh.antennapod)
|
||||
[<img src="https://f-droid.org/badge/get-it-on.png"
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="90">](https://f-droid.org/app/de.danoeh.antennapod)
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "me.tatarka.retrolambda"
|
||||
apply plugin: 'com.github.triplet.play'
|
||||
apply plugin: 'com.getkeepsafe.dexcount'
|
||||
|
||||
@ -15,7 +14,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.1'
|
||||
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,9 +83,17 @@ android {
|
||||
applicationIdSuffix ".debug"
|
||||
resValue "string", "provider_authority", "de.danoeh.antennapod.debug.provider"
|
||||
buildConfigField STRING, FLATTR_APP_KEY, mFlattrAppKey
|
||||
buildConfigField STRING, FLATTR_APP_SECRET, mFlattrAppSecret
|
||||
buildConfigField STRING, FLATTR_APP_SECRET, mFlattrAppSecret
|
||||
dexcount {
|
||||
if (project.hasProperty("enableDexcountInDebug")) {
|
||||
runOnEachPackage enableDexcountInDebug.toBoolean()
|
||||
} else { // default to not running dexcount
|
||||
runOnEachPackage false
|
||||
}
|
||||
}
|
||||
}
|
||||
release {
|
||||
resValue "string", "provider_authority", "de.danoeh.antennapod.provider"
|
||||
minifyEnabled true
|
||||
proguardFile "proguard.cfg"
|
||||
signingConfig signingConfigs.releaseConfig
|
||||
@ -113,10 +120,13 @@ android {
|
||||
additionalParameters "--no-version-vectors"
|
||||
}
|
||||
|
||||
flavorDimensions "market"
|
||||
productFlavors {
|
||||
free {
|
||||
dimension "market"
|
||||
}
|
||||
play {
|
||||
dimension "market"
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,59 +135,55 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
freeDebugCompile
|
||||
freeReleaseCompile
|
||||
playDebugCompile
|
||||
playReleaseCompile
|
||||
}
|
||||
|
||||
dependencies {
|
||||
freeDebugCompile project(path: ":core", configuration: "freeDebug")
|
||||
freeReleaseCompile project(path: ":core", configuration: "freeRelease")
|
||||
freeImplementation project(":core")
|
||||
// free build hack: skip some dependencies
|
||||
if (!doFreeBuild()) {
|
||||
playDebugCompile project(path: ":core", configuration: "playDebug")
|
||||
playReleaseCompile project(path: ":core", configuration: "playRelease")
|
||||
playImplementation project(":core")
|
||||
} else {
|
||||
System.out.println("app: free build hack, skipping some dependencies")
|
||||
}
|
||||
compile "com.android.support:support-v4:$supportVersion"
|
||||
compile "com.android.support:appcompat-v7:$supportVersion"
|
||||
compile "com.android.support:design:$supportVersion"
|
||||
compile "com.android.support:gridlayout-v7:$supportVersion"
|
||||
compile "com.android.support:percent:$supportVersion"
|
||||
compile "com.android.support:recyclerview-v7:$supportVersion"
|
||||
compile "org.apache.commons:commons-lang3:$commonslangVersion"
|
||||
compile("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") {
|
||||
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:percent:$supportVersion"
|
||||
implementation "com.android.support:recyclerview-v7:$supportVersion"
|
||||
compileOnly 'com.google.android.wearable:wearable:2.2.0'
|
||||
implementation "org.apache.commons:commons-lang3:$commonslangVersion"
|
||||
implementation("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") {
|
||||
exclude group: "org.json", module: "json"
|
||||
}
|
||||
compile "commons-io:commons-io:$commonsioVersion"
|
||||
compile "org.jsoup:jsoup:$jsoupVersion"
|
||||
compile "com.github.bumptech.glide:glide:$glideVersion"
|
||||
compile "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
||||
compile "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion"
|
||||
compile "com.squareup.okio:okio:$okioVersion"
|
||||
compile "de.greenrobot:eventbus:$eventbusVersion"
|
||||
compile "io.reactivex:rxandroid:$rxAndroidVersion"
|
||||
compile "io.reactivex:rxjava:$rxJavaVersion"
|
||||
implementation "commons-io:commons-io:$commonsioVersion"
|
||||
implementation "org.jsoup:jsoup:$jsoupVersion"
|
||||
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
||||
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
||||
implementation "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion"
|
||||
implementation "com.squareup.okio:okio:$okioVersion"
|
||||
implementation "de.greenrobot:eventbus:$eventbusVersion"
|
||||
implementation "io.reactivex:rxandroid:$rxAndroidVersion"
|
||||
implementation "io.reactivex:rxjava:$rxJavaVersion"
|
||||
// And ProGuard rules for RxJava!
|
||||
compile "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion"
|
||||
compile "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyVersion"
|
||||
compile "com.joanzapata.iconify:android-iconify-material:$iconifyVersion"
|
||||
compile("com.afollestad.material-dialogs:commons:$materialDialogsVersion") {
|
||||
implementation "com.artemzin.rxjava:proguard-rules:$rxJavaRulesVersion"
|
||||
implementation "com.joanzapata.iconify:android-iconify-fontawesome:$iconifyVersion"
|
||||
implementation "com.joanzapata.iconify:android-iconify-material:$iconifyVersion"
|
||||
implementation("com.afollestad.material-dialogs:commons:$materialDialogsVersion") {
|
||||
transitive = true
|
||||
}
|
||||
compile "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion"
|
||||
compile("com.githang:viewpagerindicator:2.5@aar") {
|
||||
implementation "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion"
|
||||
implementation("com.githang:viewpagerindicator:2.5.1@aar") {
|
||||
exclude module: "support-v4"
|
||||
}
|
||||
|
||||
compile "com.github.shts:TriangleLabelView:$triangleLabelViewVersion"
|
||||
implementation "com.github.shts:TriangleLabelView:$triangleLabelViewVersion"
|
||||
|
||||
compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
|
||||
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
|
||||
|
||||
compile 'com.github.mfietz:fyydlin:v0.3'
|
||||
implementation 'com.github.mfietz:fyydlin:v0.3'
|
||||
implementation 'com.github.ByteHamster:SearchPreference:v1.0.8'
|
||||
|
||||
androidTestImplementation "com.jayway.android.robotium:robotium-solo:$robotiumSoloVersion"
|
||||
}
|
||||
|
||||
play {
|
||||
|
@ -125,3 +125,13 @@
|
||||
-keep class com.squareup.moshi.** { *; }
|
||||
-keep interface com.squareup.moshi.** { *; }
|
||||
-keep public class retrofit2.adapter.rxjava.RxJavaCallAdapterFactory { *; }
|
||||
|
||||
# awaitility
|
||||
-dontwarn java.beans.BeanInfo
|
||||
-dontwarn java.beans.Introspector
|
||||
-dontwarn java.beans.IntrospectionException
|
||||
-dontwarn java.beans.PropertyDescriptor
|
||||
-dontwarn java.lang.management.ManagementFactory
|
||||
-dontwarn java.lang.management.ThreadInfo
|
||||
-dontwarn java.lang.management.ThreadMXBean
|
||||
|
||||
|
34
app/sampledata/episodes.json
Normal file
34
app/sampledata/episodes.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"title": "FLOSS Weekly 482: PyPI",
|
||||
"status_label": "NEW",
|
||||
"duration": "00:52:40",
|
||||
"published_at": "2. May"
|
||||
},
|
||||
{
|
||||
"title": "FLOSS Weekly 479: Pidgin",
|
||||
"status_label": " ",
|
||||
"duration": "01:08:08",
|
||||
"published_at": "11. Apr"
|
||||
},
|
||||
{
|
||||
"title": "Linux Outlaws 370 - Stay Free, Stay Open Source",
|
||||
"status_label": "NEW",
|
||||
"duration": "02:52:51",
|
||||
"published_at": "29. Dec 2014"
|
||||
},
|
||||
{
|
||||
"title": "Linux Outlaws 368 - The Dark Ages of Free Software",
|
||||
"status_label": " ",
|
||||
"duration": "02:26:54",
|
||||
"published_at": "14. Dec 2014"
|
||||
},
|
||||
{
|
||||
"title": "Linux Outlaws 365 - Last Stand",
|
||||
"status_label": " ",
|
||||
"duration": "00:39:59",
|
||||
"published_at": "3. Nov 2014"
|
||||
}
|
||||
]
|
||||
}
|
2
app/sampledata/inplaylist
Normal file
2
app/sampledata/inplaylist
Normal file
@ -0,0 +1,2 @@
|
||||
@null
|
||||
@drawable/ic_list_grey600_24dp
|
3
app/sampledata/secondaryaction
Normal file
3
app/sampledata/secondaryaction
Normal file
@ -0,0 +1,3 @@
|
||||
@drawable/ic_play_arrow_grey600_36dp
|
||||
@drawable/ic_file_download_grey600_24dp
|
||||
@drawable/ic_cancel_grey600_24dp
|
@ -0,0 +1,37 @@
|
||||
package de.test.antennapod.feed;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
|
||||
public class FeedItemTest extends AndroidTestCase {
|
||||
private static final String TEXT_LONG = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
private static final String TEXT_SHORT = "Lorem ipsum";
|
||||
|
||||
/**
|
||||
* If one of `description` or `content:encoded` is null, use the other one.
|
||||
*/
|
||||
public void testShownotesNullValues() throws Exception {
|
||||
testShownotes(null, TEXT_LONG);
|
||||
testShownotes(TEXT_LONG, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* If `description` is reasonably longer than `content:encoded`, use `description`.
|
||||
*/
|
||||
public void testShownotesLength() throws Exception {
|
||||
testShownotes(TEXT_SHORT, TEXT_LONG);
|
||||
testShownotes(TEXT_LONG, TEXT_SHORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the shownotes equal TEXT_LONG, using the given `description` and `content:encoded`
|
||||
* @param description Description of the feed item
|
||||
* @param contentEncoded `content:encoded` of the feed item
|
||||
*/
|
||||
private void testShownotes(String description, String contentEncoded) throws Exception {
|
||||
FeedItem item = new FeedItem();
|
||||
item.setDescription(description);
|
||||
item.setContentEncoded(contentEncoded);
|
||||
assertEquals(TEXT_LONG, item.loadShownotes().call());
|
||||
}
|
||||
}
|
@ -2,14 +2,16 @@ package de.test.antennapod.gpodnet;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.gpoddernet.GpodnetService;
|
||||
import de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException;
|
||||
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice;
|
||||
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetTag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Test class for GpodnetService
|
||||
@ -55,7 +57,7 @@ public class GPodnetServiceTest extends AndroidTestCase {
|
||||
authenticate();
|
||||
String[] URLS = {"http://bitsundso.de/feed", "http://gamesundso.de/feed", "http://cre.fm/feed/mp3/", "http://freakshow.fm/feed/m4a/"};
|
||||
List<String> subscriptions = Arrays.asList(URLS[0], URLS[1]);
|
||||
List<String> removed = Arrays.asList(URLS[0]);
|
||||
List<String> removed = singletonList(URLS[0]);
|
||||
List<String> added = Arrays.asList(URLS[2], URLS[3]);
|
||||
service.uploadSubscriptions(USER, "radio", subscriptions);
|
||||
service.uploadChanges(USER, "radio", added, removed);
|
||||
|
@ -17,7 +17,6 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
|
||||
@ -32,8 +31,8 @@ import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator;
|
||||
public class FeedHandlerTest extends InstrumentationTestCase {
|
||||
private static final String FEEDS_DIR = "testfeeds";
|
||||
|
||||
File file = null;
|
||||
OutputStream outputStream = null;
|
||||
private File file = null;
|
||||
private OutputStream outputStream = null;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@ -82,15 +81,7 @@ public class FeedHandlerTest extends InstrumentationTestCase {
|
||||
assertEquals(feed.getLink(), parsedFeed.getLink());
|
||||
assertEquals(feed.getDescription(), parsedFeed.getDescription());
|
||||
assertEquals(feed.getPaymentLink(), parsedFeed.getPaymentLink());
|
||||
|
||||
if (feed.getImage() != null) {
|
||||
FeedImage image = feed.getImage();
|
||||
FeedImage parsedImage = parsedFeed.getImage();
|
||||
assertNotNull(parsedImage);
|
||||
|
||||
assertEquals(image.getTitle(), parsedImage.getTitle());
|
||||
assertEquals(image.getDownload_url(), parsedImage.getDownload_url());
|
||||
}
|
||||
assertEquals(feed.getImageUrl(), parsedFeed.getImageUrl());
|
||||
|
||||
if (feed.getItems() != null) {
|
||||
assertNotNull(parsedFeed.getItems());
|
||||
@ -119,14 +110,7 @@ public class FeedHandlerTest extends InstrumentationTestCase {
|
||||
assertEquals(media.getMime_type(), parsedMedia.getMime_type());
|
||||
}
|
||||
|
||||
if (item.hasItemImage()) {
|
||||
assertTrue(parsedItem.hasItemImage());
|
||||
FeedImage image = item.getImage();
|
||||
FeedImage parsedImage = parsedItem.getImage();
|
||||
|
||||
assertEquals(image.getTitle(), parsedImage.getTitle());
|
||||
assertEquals(image.getDownload_url(), parsedImage.getDownload_url());
|
||||
}
|
||||
assertEquals(item.getImageUrl(), parsedFeed.getImageUrl());
|
||||
|
||||
if (item.getChapters() != null) {
|
||||
assertNotNull(parsedItem.getChapters());
|
||||
@ -158,14 +142,10 @@ public class FeedHandlerTest extends InstrumentationTestCase {
|
||||
}
|
||||
|
||||
private Feed createTestFeed(int numItems, boolean withImage, boolean withFeedMedia, boolean withChapters) {
|
||||
FeedImage image = null;
|
||||
if (withImage) {
|
||||
image = new FeedImage(0, "image", null, "http://example.com/picture", false);
|
||||
}
|
||||
Feed feed = new Feed(0, null, "title", "http://example.com", "This is the description",
|
||||
"http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", image, file.getAbsolutePath(),
|
||||
"http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", "http://example.com/picture", file.getAbsolutePath(),
|
||||
"http://example.com/feed", true);
|
||||
feed.setItems(new ArrayList<FeedItem>());
|
||||
feed.setItems(new ArrayList<>());
|
||||
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
FeedItem item = new FeedItem(0, "item-" + i, "http://example.com/item-" + i,
|
||||
|
@ -23,8 +23,8 @@ import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
|
||||
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
|
||||
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
|
@ -9,10 +9,10 @@ import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackServiceTaskManager;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
|
@ -27,12 +27,12 @@ import static de.test.antennapod.storage.DBTestUtils.saveFeedlist;
|
||||
public class DBCleanupTests extends InstrumentationTestCase {
|
||||
|
||||
private static final String TAG = "DBTasksTest";
|
||||
protected static final int EPISODE_CACHE_SIZE = 5;
|
||||
static final int EPISODE_CACHE_SIZE = 5;
|
||||
private final int cleanupAlgorithm;
|
||||
|
||||
protected Context context;
|
||||
Context context;
|
||||
|
||||
protected File destFolder;
|
||||
private File destFolder;
|
||||
|
||||
public DBCleanupTests() {
|
||||
this.cleanupAlgorithm = UserPreferences.EPISODE_CLEANUP_DEFAULT;
|
||||
@ -104,9 +104,9 @@ public class DBCleanupTests extends InstrumentationTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
protected void populateItems(final int numItems, Feed feed, List<FeedItem> items,
|
||||
List<File> files, int itemState, boolean addToQueue,
|
||||
boolean addToFavorites) throws IOException {
|
||||
void populateItems(final int numItems, Feed feed, List<FeedItem> items,
|
||||
List<File> files, int itemState, boolean addToQueue,
|
||||
boolean addToFavorites) throws IOException {
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
Date itemDate = new Date(numItems - i);
|
||||
Date playbackCompletionDate = null;
|
||||
|
@ -5,7 +5,6 @@ import android.test.FlakyTest;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
|
@ -18,6 +18,8 @@ import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Test class for DBTasks
|
||||
*/
|
||||
@ -125,7 +127,7 @@ public class DBTasksTest extends InstrumentationTestCase {
|
||||
public void testUpdateFeedMediaUrlResetState() {
|
||||
final Feed feed = new Feed("url", null, "title");
|
||||
FeedItem item = new FeedItem(0, "item", "id", "link", new Date(), FeedItem.PLAYED, feed);
|
||||
feed.setItems(Arrays.asList(item));
|
||||
feed.setItems(singletonList(item));
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
@ -138,7 +140,7 @@ public class DBTasksTest extends InstrumentationTestCase {
|
||||
|
||||
FeedMedia media = new FeedMedia(item, "url", 1024, "mime/type");
|
||||
item.setMedia(media);
|
||||
feed.setItems(Arrays.asList(item));
|
||||
feed.setItems(singletonList(item));
|
||||
|
||||
final Feed newFeed = DBTasks.updateFeed(context, feed)[0];
|
||||
assertTrue(feed != newFeed);
|
||||
|
@ -19,7 +19,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
|
||||
/**
|
||||
* Utility methods for DB* tests.
|
||||
*/
|
||||
public class DBTestUtils {
|
||||
class DBTestUtils {
|
||||
|
||||
private DBTestUtils(){}
|
||||
/**
|
||||
|
@ -15,9 +15,7 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.feed.SimpleChapter;
|
||||
@ -124,89 +122,13 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
assertNull(media.getFile_url());
|
||||
}
|
||||
|
||||
public void testDeleteFeed() throws IOException, ExecutionException, InterruptedException, TimeoutException {
|
||||
public void testDeleteFeed() throws ExecutionException, InterruptedException, IOException, TimeoutException {
|
||||
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
|
||||
assertNotNull(destFolder);
|
||||
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<>());
|
||||
|
||||
// create Feed image
|
||||
File imgFile = new File(destFolder, "image");
|
||||
assertTrue(imgFile.createNewFile());
|
||||
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
|
||||
image.setOwner(feed);
|
||||
feed.setImage(image);
|
||||
|
||||
List<File> itemFiles = new ArrayList<>();
|
||||
// create items with downloaded media files
|
||||
for (int i = 0; i < 10; i++) {
|
||||
FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed, true);
|
||||
feed.getItems().add(item);
|
||||
|
||||
File enc = new File(destFolder, "file " + i);
|
||||
assertTrue(enc.createNewFile());
|
||||
itemFiles.add(enc);
|
||||
|
||||
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", enc.getAbsolutePath(), "download_url", true, null, 0, 0);
|
||||
item.setMedia(media);
|
||||
|
||||
item.setChapters(new ArrayList<Chapter>());
|
||||
item.getChapters().add(new SimpleChapter(0, "item " + i, item, "example.com"));
|
||||
}
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setCompleteFeed(feed);
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
assertTrue(feed.getImage().getId() != 0);
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
assertTrue(item.getChapters().get(0).getId() != 0);
|
||||
}
|
||||
|
||||
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
// check if files still exist
|
||||
assertFalse(imgFile.exists());
|
||||
for (File f : itemFiles) {
|
||||
assertFalse(f.exists());
|
||||
}
|
||||
|
||||
adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
Cursor c = adapter.getFeedCursor(feed.getId());
|
||||
assertEquals(0, c.getCount());
|
||||
c.close();
|
||||
c = adapter.getImageCursor(String.valueOf(image.getId()));
|
||||
assertEquals(0, c.getCount());
|
||||
c.close();
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
|
||||
assertEquals(0, c.getCount());
|
||||
c.close();
|
||||
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
|
||||
assertEquals(0, c.getCount());
|
||||
c.close();
|
||||
c = adapter.getSimpleChaptersOfFeedItemCursor(item);
|
||||
assertEquals(0, c.getCount());
|
||||
c.close();
|
||||
}
|
||||
adapter.close();
|
||||
}
|
||||
|
||||
public void testDeleteFeedNoImage() throws ExecutionException, InterruptedException, IOException, TimeoutException {
|
||||
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
|
||||
assertNotNull(destFolder);
|
||||
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<>());
|
||||
|
||||
feed.setImage(null);
|
||||
|
||||
List<File> itemFiles = new ArrayList<>();
|
||||
// create items with downloaded media files
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@ -261,13 +183,7 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(null);
|
||||
|
||||
// create Feed image
|
||||
File imgFile = new File(destFolder, "image");
|
||||
assertTrue(imgFile.createNewFile());
|
||||
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
|
||||
image.setOwner(feed);
|
||||
feed.setImage(image);
|
||||
feed.setImageUrl("url");
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
@ -275,21 +191,14 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
assertTrue(feed.getImage().getId() != 0);
|
||||
|
||||
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
// check if files still exist
|
||||
assertFalse(imgFile.exists());
|
||||
|
||||
adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
Cursor c = adapter.getFeedCursor(feed.getId());
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
c = adapter.getImageCursor(String.valueOf(image.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
adapter.close();
|
||||
}
|
||||
|
||||
@ -300,12 +209,7 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<>());
|
||||
|
||||
// create Feed image
|
||||
File imgFile = new File(destFolder, "image");
|
||||
assertTrue(imgFile.createNewFile());
|
||||
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
|
||||
image.setOwner(feed);
|
||||
feed.setImage(image);
|
||||
feed.setImageUrl("url");
|
||||
|
||||
// create items
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@ -320,24 +224,18 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
assertTrue(feed.getImage().getId() != 0);
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
assertTrue(item.getId() != 0);
|
||||
}
|
||||
|
||||
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
// check if files still exist
|
||||
assertFalse(imgFile.exists());
|
||||
|
||||
adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
Cursor c = adapter.getFeedCursor(feed.getId());
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
c = adapter.getImageCursor(String.valueOf(image.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
@ -346,65 +244,6 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
adapter.close();
|
||||
}
|
||||
|
||||
public void testDeleteFeedWithItemImages() throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
||||
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
|
||||
assertNotNull(destFolder);
|
||||
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<>());
|
||||
|
||||
// create Feed image
|
||||
File imgFile = new File(destFolder, "image");
|
||||
assertTrue(imgFile.createNewFile());
|
||||
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
|
||||
image.setOwner(feed);
|
||||
feed.setImage(image);
|
||||
|
||||
// create items with images
|
||||
for (int i = 0; i < 10; i++) {
|
||||
FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed);
|
||||
feed.getItems().add(item);
|
||||
File itemImageFile = new File(destFolder, "item-image-" + i);
|
||||
FeedImage itemImage = new FeedImage(0, "item-image" + i, itemImageFile.getAbsolutePath(), "url", true);
|
||||
item.setImage(itemImage);
|
||||
}
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setCompleteFeed(feed);
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
assertTrue(feed.getImage().getId() != 0);
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getImage().getId() != 0);
|
||||
}
|
||||
|
||||
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
|
||||
|
||||
// check if files still exist
|
||||
assertFalse(imgFile.exists());
|
||||
|
||||
adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
Cursor c = adapter.getFeedCursor(feed.getId());
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
c = adapter.getImageCursor(String.valueOf(image.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
c = adapter.getImageCursor(String.valueOf(item.getImage().getId()));
|
||||
assertEquals(0, c.getCount());
|
||||
c.close();
|
||||
}
|
||||
adapter.close();
|
||||
}
|
||||
|
||||
public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException {
|
||||
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
|
||||
assertNotNull(destFolder);
|
||||
@ -412,11 +251,7 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<>());
|
||||
|
||||
// create Feed image
|
||||
File imgFile = new File(destFolder, "image");
|
||||
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
|
||||
image.setOwner(feed);
|
||||
feed.setImage(image);
|
||||
feed.setImageUrl("url");
|
||||
|
||||
List<File> itemFiles = new ArrayList<>();
|
||||
// create items with downloaded media files
|
||||
@ -437,7 +272,6 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
assertTrue(feed.getImage().getId() != 0);
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
@ -460,9 +294,6 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
Cursor c = adapter.getFeedCursor(feed.getId());
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
c = adapter.getImageCursor(String.valueOf(image.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
@ -484,11 +315,7 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<>());
|
||||
|
||||
// create Feed image
|
||||
File imgFile = new File(destFolder, "image");
|
||||
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
|
||||
image.setOwner(feed);
|
||||
feed.setImage(image);
|
||||
feed.setImageUrl("url");
|
||||
|
||||
List<File> itemFiles = new ArrayList<>();
|
||||
// create items with downloaded media files
|
||||
@ -509,7 +336,6 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
assertTrue(feed.getImage().getId() != 0);
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
@ -522,9 +348,6 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
Cursor c = adapter.getFeedCursor(feed.getId());
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
c = adapter.getImageCursor(String.valueOf(image.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
c.close();
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
|
||||
assertTrue(c.getCount() == 0);
|
||||
@ -539,7 +362,7 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
private FeedMedia playbackHistorySetup(Date playbackCompletionDate) {
|
||||
final Context context = getInstrumentation().getTargetContext();
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<FeedItem>());
|
||||
feed.setItems(new ArrayList<>());
|
||||
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
|
||||
FeedMedia media = new FeedMedia(0, item, 10, 0, 1, "mime", null, "url", false, playbackCompletionDate, 0, 0);
|
||||
feed.getItems().add(item);
|
||||
@ -791,7 +614,7 @@ public class DBWriterTest extends InstrumentationTestCase {
|
||||
public void testMarkFeedRead() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
final int NUM_ITEMS = 10;
|
||||
Feed feed = new Feed("url", null, "title");
|
||||
feed.setItems(new ArrayList<FeedItem>());
|
||||
feed.setItems(new ArrayList<>());
|
||||
for (int i = 0; i < NUM_ITEMS; i++) {
|
||||
FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.UNPLAYED, feed);
|
||||
feed.getItems().add(item);
|
||||
|
@ -15,6 +15,7 @@ import java.util.List;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
|
||||
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
@ -22,7 +23,6 @@ import de.danoeh.antennapod.fragment.DownloadsFragment;
|
||||
import de.danoeh.antennapod.fragment.EpisodesFragment;
|
||||
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
|
||||
import de.danoeh.antennapod.fragment.QueueFragment;
|
||||
import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
|
||||
/**
|
||||
* User interface tests for MainActivity
|
||||
@ -96,7 +96,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
|
||||
public void testClickNavDrawer() throws Exception {
|
||||
uiTestUtils.addLocalFeedData(false);
|
||||
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<>());
|
||||
|
||||
// queue
|
||||
openNavDrawer();
|
||||
@ -155,11 +155,11 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
|
||||
public void testGoToPreferences() {
|
||||
openNavDrawer();
|
||||
solo.clickOnText(solo.getString(R.string.settings_label));
|
||||
solo.waitForActivity(PreferenceController.getPreferenceActivity());
|
||||
solo.waitForActivity(PreferenceActivity.class);
|
||||
}
|
||||
|
||||
public void testDrawerPreferencesHideSomeElements() {
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<>());
|
||||
openNavDrawer();
|
||||
solo.clickLongOnText(solo.getString(R.string.queue_label));
|
||||
solo.waitForDialogToOpen();
|
||||
@ -190,7 +190,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
|
||||
}
|
||||
|
||||
public void testDrawerPreferencesHideAllElements() {
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<>());
|
||||
String[] titles = getInstrumentation().getTargetContext().getResources().getStringArray(R.array.nav_drawer_titles);
|
||||
|
||||
openNavDrawer();
|
||||
@ -209,7 +209,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
|
||||
}
|
||||
|
||||
public void testDrawerPreferencesHideCurrentElement() {
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
|
||||
UserPreferences.setHiddenDrawerItems(new ArrayList<>());
|
||||
|
||||
openNavDrawer();
|
||||
String downloads = solo.getString(R.string.downloads_label);
|
||||
|
@ -33,8 +33,8 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
public class PlaybackSonicTest extends ActivityInstrumentationTestCase2<MainActivity> {
|
||||
|
||||
private static final String TAG = PlaybackTest.class.getSimpleName();
|
||||
public static final int EPISODES_DRAWER_LIST_INDEX = 1;
|
||||
public static final int QUEUE_DRAWER_LIST_INDEX = 0;
|
||||
private static final int EPISODES_DRAWER_LIST_INDEX = 1;
|
||||
private static final int QUEUE_DRAWER_LIST_INDEX = 0;
|
||||
|
||||
private Solo solo;
|
||||
private UITestUtils uiTestUtils;
|
||||
|
@ -30,8 +30,8 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity> {
|
||||
|
||||
private static final String TAG = PlaybackTest.class.getSimpleName();
|
||||
public static final int EPISODES_DRAWER_LIST_INDEX = 1;
|
||||
public static final int QUEUE_DRAWER_LIST_INDEX = 0;
|
||||
private static final int EPISODES_DRAWER_LIST_INDEX = 1;
|
||||
private static final int QUEUE_DRAWER_LIST_INDEX = 0;
|
||||
|
||||
private Solo solo;
|
||||
private UITestUtils uiTestUtils;
|
||||
|
@ -3,7 +3,6 @@ package de.test.antennapod.ui;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.util.Log;
|
||||
|
||||
import com.robotium.solo.Solo;
|
||||
import com.robotium.solo.Timeout;
|
||||
@ -56,6 +55,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
} else {
|
||||
otherTheme = R.string.pref_theme_title_light;
|
||||
}
|
||||
solo.clickOnText(solo.getString(R.string.user_interface_label));
|
||||
solo.clickOnText(solo.getString(R.string.pref_set_theme_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clickOnText(solo.getString(otherTheme));
|
||||
@ -70,6 +70,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
} else {
|
||||
otherTheme = R.string.pref_theme_title_light;
|
||||
}
|
||||
solo.clickOnText(solo.getString(R.string.user_interface_label));
|
||||
solo.clickOnText(solo.getString(R.string.pref_set_theme_title));
|
||||
solo.waitForDialogToOpen(1000);
|
||||
solo.clickOnText(solo.getString(otherTheme));
|
||||
@ -77,6 +78,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testExpandNotification() {
|
||||
solo.clickOnText(solo.getString(R.string.user_interface_label));
|
||||
final int priority = UserPreferences.getNotifyPriority();
|
||||
solo.clickOnText(solo.getString(R.string.pref_expandNotify_title));
|
||||
assertTrue(solo.waitForCondition(() -> priority != UserPreferences.getNotifyPriority(), Timeout.getLargeTimeout()));
|
||||
@ -85,7 +87,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testEnablePersistentPlaybackControls() {
|
||||
solo.clickOnText(solo.getString(R.string.user_interface_label));
|
||||
final boolean persistNotify = UserPreferences.isPersistNotify();
|
||||
solo.scrollDown();
|
||||
solo.scrollDown();
|
||||
solo.clickOnText(solo.getString(R.string.pref_persistNotify_title));
|
||||
assertTrue(solo.waitForCondition(() -> persistNotify != UserPreferences.isPersistNotify(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_persistNotify_title));
|
||||
@ -93,14 +98,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testSetLockscreenButtons() {
|
||||
solo.clickOnText(solo.getString(R.string.user_interface_label));
|
||||
solo.scrollDown();
|
||||
String[] buttons = res.getStringArray(R.array.compact_notification_buttons_options);
|
||||
solo.clickOnText(solo.getString(R.string.pref_compact_notification_buttons_title));
|
||||
solo.waitForDialogToOpen(1000);
|
||||
// First uncheck every checkbox
|
||||
for (int i=0; i<buttons.length; i++) {
|
||||
assertTrue(solo.searchText(buttons[i]));
|
||||
if (solo.isTextChecked(buttons[i])) {
|
||||
solo.clickOnText(buttons[i]);
|
||||
for (String button : buttons) {
|
||||
assertTrue(solo.searchText(button));
|
||||
if (solo.isTextChecked(button)) {
|
||||
solo.clickOnText(button);
|
||||
}
|
||||
}
|
||||
// Now try to check all checkboxes
|
||||
@ -111,13 +118,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
assertTrue(!solo.isTextChecked(buttons[2]));
|
||||
solo.clickOnText(solo.getString(R.string.confirm_label));
|
||||
solo.waitForDialogToClose(1000);
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.showRewindOnCompactNotification(), Timeout.getLargeTimeout()));
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.showFastForwardOnCompactNotification(), Timeout.getLargeTimeout()));
|
||||
assertTrue(solo.waitForCondition(UserPreferences::showRewindOnCompactNotification, Timeout.getLargeTimeout()));
|
||||
assertTrue(solo.waitForCondition(UserPreferences::showFastForwardOnCompactNotification, Timeout.getLargeTimeout()));
|
||||
assertTrue(solo.waitForCondition(() -> !UserPreferences.showSkipOnCompactNotification(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testEnqueueAtFront() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
final boolean enqueueAtFront = UserPreferences.enqueueAtFront();
|
||||
solo.scrollDown();
|
||||
solo.scrollDown();
|
||||
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));
|
||||
assertTrue(solo.waitForCondition(() -> enqueueAtFront != UserPreferences.enqueueAtFront(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));
|
||||
@ -125,6 +135,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testHeadPhonesDisconnect() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
final boolean pauseOnHeadsetDisconnect = UserPreferences.isPauseOnHeadsetDisconnect();
|
||||
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
|
||||
assertTrue(solo.waitForCondition(() -> pauseOnHeadsetDisconnect != UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
|
||||
@ -133,9 +144,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testHeadPhonesReconnect() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
if(UserPreferences.isPauseOnHeadsetDisconnect() == false) {
|
||||
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
|
||||
assertTrue(solo.waitForCondition(UserPreferences::isPauseOnHeadsetDisconnect, Timeout.getLargeTimeout()));
|
||||
}
|
||||
final boolean unpauseOnHeadsetReconnect = UserPreferences.isUnpauseOnHeadsetReconnect();
|
||||
solo.clickOnText(solo.getString(R.string.pref_unpauseOnHeadsetReconnect_title));
|
||||
@ -145,9 +157,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testBluetoothReconnect() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
if(UserPreferences.isPauseOnHeadsetDisconnect() == false) {
|
||||
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
|
||||
assertTrue(solo.waitForCondition(UserPreferences::isPauseOnHeadsetDisconnect, Timeout.getLargeTimeout()));
|
||||
}
|
||||
final boolean unpauseOnBluetoothReconnect = UserPreferences.isUnpauseOnBluetoothReconnect();
|
||||
solo.clickOnText(solo.getString(R.string.pref_unpauseOnBluetoothReconnect_title));
|
||||
@ -157,7 +170,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testContinuousPlayback() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
final boolean continuousPlayback = UserPreferences.isFollowQueue();
|
||||
solo.scrollDown();
|
||||
solo.scrollDown();
|
||||
solo.clickOnText(solo.getString(R.string.pref_followQueue_title));
|
||||
assertTrue(solo.waitForCondition(() -> continuousPlayback != UserPreferences.isFollowQueue(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_followQueue_title));
|
||||
@ -165,6 +181,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testAutoDelete() {
|
||||
solo.clickOnText(solo.getString(R.string.storage_pref));
|
||||
final boolean autoDelete = UserPreferences.isAutoDelete();
|
||||
solo.clickOnText(solo.getString(R.string.pref_auto_delete_title));
|
||||
assertTrue(solo.waitForCondition(() -> autoDelete != UserPreferences.isAutoDelete(), Timeout.getLargeTimeout()));
|
||||
@ -173,6 +190,9 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testPlaybackSpeeds() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
solo.scrollDown();
|
||||
solo.scrollDown();
|
||||
solo.clickOnText(solo.getString(R.string.pref_playback_speed_title));
|
||||
solo.waitForDialogToOpen(1000);
|
||||
assertTrue(solo.searchText(res.getStringArray(R.array.playback_speed_values)[0]));
|
||||
@ -181,6 +201,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testPauseForInterruptions() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
final boolean pauseForFocusLoss = UserPreferences.shouldPauseForFocusLoss();
|
||||
solo.clickOnText(solo.getString(R.string.pref_pausePlaybackForFocusLoss_title));
|
||||
assertTrue(solo.waitForCondition(() -> pauseForFocusLoss != UserPreferences.shouldPauseForFocusLoss(), Timeout.getLargeTimeout()));
|
||||
@ -189,6 +210,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testDisableUpdateInterval() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_sum));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_Disable));
|
||||
@ -196,6 +218,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testSetUpdateInterval() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_Interval));
|
||||
@ -208,6 +231,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testMobileUpdates() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
final boolean mobileUpdates = UserPreferences.isAllowMobileUpdate();
|
||||
solo.clickOnText(solo.getString(R.string.pref_mobileUpdate_title));
|
||||
assertTrue(solo.waitForCondition(() -> mobileUpdates != UserPreferences.isAllowMobileUpdate(), Timeout.getLargeTimeout()));
|
||||
@ -216,6 +240,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testSetSequentialDownload() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clearEditText(0);
|
||||
@ -225,6 +250,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testSetParallelDownloads() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clearEditText(0);
|
||||
@ -234,6 +260,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testSetParallelDownloadsInvalidInput() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clearEditText(0);
|
||||
@ -249,6 +276,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
String[] values = res.getStringArray(R.array.episode_cache_size_values);
|
||||
String entry = entries[entries.length/2];
|
||||
final int value = Integer.valueOf(values[values.length/2]);
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cache_title));
|
||||
@ -262,6 +290,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
String[] values = res.getStringArray(R.array.episode_cache_size_values);
|
||||
String minEntry = entries[0];
|
||||
final int minValue = Integer.valueOf(values[0]);
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
|
||||
if(!UserPreferences.isEnableAutodownload()) {
|
||||
@ -279,6 +308,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
String[] values = res.getStringArray(R.array.episode_cache_size_values);
|
||||
String maxEntry = entries[entries.length-1];
|
||||
final int maxValue = Integer.valueOf(values[values.length-1]);
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
|
||||
if(!UserPreferences.isEnableAutodownload()) {
|
||||
@ -292,6 +322,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
|
||||
public void testAutomaticDownload() {
|
||||
final boolean automaticDownload = UserPreferences.isEnableAutodownload();
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
@ -313,6 +344,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testEpisodeCleanupQueueOnly() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_queue_removal));
|
||||
solo.clickOnText(solo.getString(R.string.episode_cleanup_queue_removal));
|
||||
@ -324,6 +357,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testEpisodeCleanupNeverAlg() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_never));
|
||||
solo.clickOnText(solo.getString(R.string.episode_cleanup_never));
|
||||
@ -335,6 +370,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testEpisodeCleanupClassic() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_after_listening));
|
||||
solo.clickOnText(solo.getString(R.string.episode_cleanup_after_listening));
|
||||
@ -350,6 +387,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testEpisodeCleanupNumDays() {
|
||||
solo.clickOnText(solo.getString(R.string.network_pref));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_after_listening));
|
||||
solo.clickOnText("5");
|
||||
@ -369,6 +408,9 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
int seconds = UserPreferences.getRewindSecs();
|
||||
int deltas[] = res.getIntArray(R.array.seek_delta_values);
|
||||
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
solo.scrollDown();
|
||||
solo.scrollDown();
|
||||
solo.clickOnText(solo.getString(R.string.pref_rewind));
|
||||
solo.waitForDialogToOpen();
|
||||
|
||||
@ -387,6 +429,9 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
}
|
||||
|
||||
public void testFastForwardChange() {
|
||||
solo.clickOnText(solo.getString(R.string.playback_pref));
|
||||
solo.scrollDown();
|
||||
solo.scrollDown();
|
||||
for (int i = 2; i > 0; i--) { // repeat twice to catch any error where fastforward is tracking rewind
|
||||
int seconds = UserPreferences.getFastForwardSecs();
|
||||
int deltas[] = res.getIntArray(R.array.seek_delta_values);
|
||||
|
@ -1,9 +1,7 @@
|
||||
package de.test.antennapod.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import junit.framework.Assert;
|
||||
@ -20,14 +18,12 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||
import de.danoeh.antennapod.fragment.ExternalPlayerFragment;
|
||||
@ -39,27 +35,25 @@ import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator;
|
||||
* Utility methods for UI tests.
|
||||
* Starts a web server that hosts feeds, episodes and images.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public class UITestUtils {
|
||||
class UITestUtils {
|
||||
|
||||
private static final String TAG = UITestUtils.class.getSimpleName();
|
||||
|
||||
private static final String DATA_FOLDER = "test/UITestUtils";
|
||||
|
||||
public static final int NUM_FEEDS = 5;
|
||||
public static final int NUM_ITEMS_PER_FEED = 10;
|
||||
private static final int NUM_FEEDS = 5;
|
||||
private static final int NUM_ITEMS_PER_FEED = 10;
|
||||
|
||||
public static final int HOME_VIEW = (Build.VERSION.SDK_INT >= 11) ? android.R.id.home : R.id.home;
|
||||
public static final String TEST_FILE_NAME = "3sec.mp3";
|
||||
private static final String TEST_FILE_NAME = "3sec.mp3";
|
||||
|
||||
|
||||
private Context context;
|
||||
private HTTPBin server = new HTTPBin();
|
||||
private final Context context;
|
||||
private final HTTPBin server = new HTTPBin();
|
||||
private File destDir;
|
||||
private File hostedFeedDir;
|
||||
private File hostedMediaDir;
|
||||
|
||||
public List<Feed> hostedFeeds = new ArrayList<>();
|
||||
public final List<Feed> hostedFeeds = new ArrayList<>();
|
||||
|
||||
public UITestUtils(Context context) {
|
||||
this.context = context;
|
||||
@ -141,12 +135,9 @@ public class UITestUtils {
|
||||
public void addHostedFeedData() throws IOException {
|
||||
if (feedDataHosted) throw new IllegalStateException("addHostedFeedData was called twice on the same instance");
|
||||
for (int i = 0; i < NUM_FEEDS; i++) {
|
||||
File bitmapFile = newBitmapFile("image" + i);
|
||||
FeedImage image = new FeedImage(0, "image " + i, null, hostFile(bitmapFile), false);
|
||||
Feed feed = new Feed(0, null, "Title " + i, "http://example.com/" + i, "Description of feed " + i,
|
||||
"http://example.com/pay/feed" + i, "author " + i, "en", Feed.TYPE_RSS2, "feed" + i, image, null,
|
||||
"http://example.com/pay/feed" + i, "author " + i, "en", Feed.TYPE_RSS2, "feed" + i, null, null,
|
||||
"http://example.com/feed/src/" + i, false);
|
||||
image.setOwner(feed);
|
||||
|
||||
// create items
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
@ -192,12 +183,6 @@ public class UITestUtils {
|
||||
List<FeedItem> queue = new ArrayList<>();
|
||||
for (Feed feed : hostedFeeds) {
|
||||
feed.setDownloaded(true);
|
||||
if (feed.getImage() != null) {
|
||||
FeedImage image = feed.getImage();
|
||||
int fileId = Integer.parseInt(StringUtils.substringAfter(image.getDownload_url(), "files/"));
|
||||
image.setFile_url(server.accessFile(fileId).getAbsolutePath());
|
||||
image.setDownloaded(true);
|
||||
}
|
||||
if (downloadEpisodes) {
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
if (item.hasMedia()) {
|
||||
|
@ -38,9 +38,6 @@ public class UITestUtilsTest extends InstrumentationTestCase {
|
||||
|
||||
for (Feed feed : feeds) {
|
||||
testUrlReachable(feed.getDownload_url());
|
||||
if (feed.getImage() != null) {
|
||||
testUrlReachable(feed.getImage().getDownload_url());
|
||||
}
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
if (item.hasMedia()) {
|
||||
testUrlReachable(item.getMedia().getDownload_url());
|
||||
@ -66,9 +63,6 @@ public class UITestUtilsTest extends InstrumentationTestCase {
|
||||
|
||||
for (Feed feed : uiTestUtils.hostedFeeds) {
|
||||
assertTrue(feed.getId() != 0);
|
||||
if (feed.getImage() != null) {
|
||||
assertTrue(feed.getImage().getId() != 0);
|
||||
}
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
assertTrue(item.getId() != 0);
|
||||
if (item.hasMedia()) {
|
||||
|
@ -1,11 +1,12 @@
|
||||
package de.test.antennapod.util;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import de.danoeh.antennapod.core.util.FileNameGenerator;
|
||||
import android.test.AndroidTestCase;
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class FilenameGeneratorTest extends AndroidTestCase {
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package de.test.antennapod.util;
|
||||
|
||||
import junit.framework.*;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import de.danoeh.antennapod.core.util.*;
|
||||
import de.danoeh.antennapod.core.util.RewindAfterPauseUtils;
|
||||
|
||||
/**
|
||||
* Tests for {@link RewindAfterPauseUtils}.
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.test.antennapod.util;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import de.danoeh.antennapod.core.util.URIUtil;
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.test.antennapod.util;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
import de.danoeh.antennapod.core.util.URLChecker;
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@ public class HTTPBin extends NanoHTTPD {
|
||||
private static final String MIME_HTML = "text/html";
|
||||
private static final String MIME_PLAIN = "text/plain";
|
||||
|
||||
private List<File> servedFiles;
|
||||
private final List<File> servedFiles;
|
||||
|
||||
public HTTPBin() {
|
||||
super(PORT);
|
||||
|
@ -88,15 +88,15 @@ public abstract class NanoHTTPD {
|
||||
* This is required as the Keep-Alive HTTP connections would otherwise
|
||||
* block the socket reading thread forever (or as long the browser is open).
|
||||
*/
|
||||
public static final int SOCKET_READ_TIMEOUT = 5000;
|
||||
private static final int SOCKET_READ_TIMEOUT = 5000;
|
||||
/**
|
||||
* Common mime type for dynamic content: plain text
|
||||
*/
|
||||
public static final String MIME_PLAINTEXT = "text/plain";
|
||||
private static final String MIME_PLAINTEXT = "text/plain";
|
||||
/**
|
||||
* Common mime type for dynamic content: html
|
||||
*/
|
||||
public static final String MIME_HTML = "text/html";
|
||||
private static final String MIME_HTML = "text/html";
|
||||
/**
|
||||
* Pseudo-Parameter to use to store the actual query string in the parameters map for later re-processing.
|
||||
*/
|
||||
@ -104,7 +104,7 @@ public abstract class NanoHTTPD {
|
||||
private final String hostname;
|
||||
private final int myPort;
|
||||
private ServerSocket myServerSocket;
|
||||
private Set<Socket> openConnections = new HashSet<>();
|
||||
private final Set<Socket> openConnections = new HashSet<>();
|
||||
private Thread myThread;
|
||||
/**
|
||||
* Pluggable strategy for asynchronously executing requests.
|
||||
@ -118,14 +118,14 @@ public abstract class NanoHTTPD {
|
||||
/**
|
||||
* Constructs an HTTP server on given port.
|
||||
*/
|
||||
public NanoHTTPD(int port) {
|
||||
NanoHTTPD(int port) {
|
||||
this(null, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an HTTP server on given hostname and port.
|
||||
*/
|
||||
public NanoHTTPD(String hostname, int port) {
|
||||
private NanoHTTPD(String hostname, int port) {
|
||||
this.hostname = hostname;
|
||||
this.myPort = port;
|
||||
setTempFileManagerFactory(new DefaultTempFileManagerFactory());
|
||||
@ -168,44 +168,38 @@ public abstract class NanoHTTPD {
|
||||
myServerSocket = new ServerSocket();
|
||||
myServerSocket.bind((hostname != null) ? new InetSocketAddress(hostname, myPort) : new InetSocketAddress(myPort));
|
||||
|
||||
myThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
do {
|
||||
try {
|
||||
final Socket finalAccept = myServerSocket.accept();
|
||||
registerConnection(finalAccept);
|
||||
finalAccept.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
final InputStream inputStream = finalAccept.getInputStream();
|
||||
asyncRunner.exec(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = finalAccept.getOutputStream();
|
||||
TempFileManager tempFileManager = tempFileManagerFactory.create();
|
||||
HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream, finalAccept.getInetAddress());
|
||||
while (!finalAccept.isClosed()) {
|
||||
session.execute();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// When the socket is closed by the client, we throw our own SocketException
|
||||
// to break the "keep alive" loop above.
|
||||
if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage()))) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
safeClose(outputStream);
|
||||
safeClose(inputStream);
|
||||
safeClose(finalAccept);
|
||||
unRegisterConnection(finalAccept);
|
||||
}
|
||||
myThread = new Thread(() -> {
|
||||
do {
|
||||
try {
|
||||
final Socket finalAccept = myServerSocket.accept();
|
||||
registerConnection(finalAccept);
|
||||
finalAccept.setSoTimeout(SOCKET_READ_TIMEOUT);
|
||||
final InputStream inputStream = finalAccept.getInputStream();
|
||||
asyncRunner.exec(() -> {
|
||||
OutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = finalAccept.getOutputStream();
|
||||
TempFileManager tempFileManager = tempFileManagerFactory.create();
|
||||
HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream, finalAccept.getInetAddress());
|
||||
while (!finalAccept.isClosed()) {
|
||||
session.execute();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
}
|
||||
} while (!myServerSocket.isClosed());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// When the socket is closed by the client, we throw our own SocketException
|
||||
// to break the "keep alive" loop above.
|
||||
if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage()))) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
safeClose(outputStream);
|
||||
safeClose(inputStream);
|
||||
safeClose(finalAccept);
|
||||
unRegisterConnection(finalAccept);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
}
|
||||
} while (!myServerSocket.isClosed());
|
||||
});
|
||||
myThread.setDaemon(true);
|
||||
myThread.setName("NanoHttpd Main Listener");
|
||||
@ -232,7 +226,7 @@ public abstract class NanoHTTPD {
|
||||
*
|
||||
* @param socket the {@link Socket} for the connection.
|
||||
*/
|
||||
public synchronized void registerConnection(Socket socket) {
|
||||
private synchronized void registerConnection(Socket socket) {
|
||||
openConnections.add(socket);
|
||||
}
|
||||
|
||||
@ -242,14 +236,14 @@ public abstract class NanoHTTPD {
|
||||
* @param socket
|
||||
* the {@link Socket} for the connection.
|
||||
*/
|
||||
public synchronized void unRegisterConnection(Socket socket) {
|
||||
private synchronized void unRegisterConnection(Socket socket) {
|
||||
openConnections.remove(socket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forcibly closes all connections that are open.
|
||||
*/
|
||||
public synchronized void closeAllConnections() {
|
||||
private synchronized void closeAllConnections() {
|
||||
for (Socket socket : openConnections) {
|
||||
safeClose(socket);
|
||||
}
|
||||
@ -259,7 +253,7 @@ public abstract class NanoHTTPD {
|
||||
return myServerSocket == null ? -1 : myServerSocket.getLocalPort();
|
||||
}
|
||||
|
||||
public final boolean wasStarted() {
|
||||
private boolean wasStarted() {
|
||||
return myServerSocket != null && myThread != null;
|
||||
}
|
||||
|
||||
@ -294,7 +288,7 @@ public abstract class NanoHTTPD {
|
||||
* @param session The HTTP session
|
||||
* @return HTTP response, see class Response for details
|
||||
*/
|
||||
public Response serve(IHTTPSession session) {
|
||||
Response serve(IHTTPSession session) {
|
||||
Map<String, String> files = new ArrayMap<>();
|
||||
Method method = session.getMethod();
|
||||
if (Method.PUT.equals(method) || Method.POST.equals(method)) {
|
||||
@ -318,7 +312,7 @@ public abstract class NanoHTTPD {
|
||||
* @param str the percent encoded <code>String</code>
|
||||
* @return expanded form of the input, for example "foo%20bar" becomes "foo bar"
|
||||
*/
|
||||
protected String decodePercent(String str) {
|
||||
private String decodePercent(String str) {
|
||||
String decoded = null;
|
||||
try {
|
||||
decoded = URLDecoder.decode(str, "UTF8");
|
||||
@ -347,7 +341,7 @@ public abstract class NanoHTTPD {
|
||||
* @param queryString a query string pulled from the URL.
|
||||
* @return a map of <code>String</code> (parameter name) to <code>List<String></code> (a list of the values supplied).
|
||||
*/
|
||||
protected Map<String, List<String>> decodeParameters(String queryString) {
|
||||
private Map<String, List<String>> decodeParameters(String queryString) {
|
||||
Map<String, List<String>> parms = new ArrayMap<>();
|
||||
if (queryString != null) {
|
||||
StringTokenizer st = new StringTokenizer(queryString, "&");
|
||||
@ -378,7 +372,7 @@ public abstract class NanoHTTPD {
|
||||
*
|
||||
* @param asyncRunner new strategy for handling threads.
|
||||
*/
|
||||
public void setAsyncRunner(AsyncRunner asyncRunner) {
|
||||
private void setAsyncRunner(AsyncRunner asyncRunner) {
|
||||
this.asyncRunner = asyncRunner;
|
||||
}
|
||||
|
||||
@ -393,7 +387,7 @@ public abstract class NanoHTTPD {
|
||||
*
|
||||
* @param tempFileManagerFactory new strategy for handling temp files.
|
||||
*/
|
||||
public void setTempFileManagerFactory(TempFileManagerFactory tempFileManagerFactory) {
|
||||
private void setTempFileManagerFactory(TempFileManagerFactory tempFileManagerFactory) {
|
||||
this.tempFileManagerFactory = tempFileManagerFactory;
|
||||
}
|
||||
|
||||
@ -448,9 +442,9 @@ public abstract class NanoHTTPD {
|
||||
* themselves up when no longer needed.</p>
|
||||
*/
|
||||
public interface TempFile {
|
||||
OutputStream open() throws Exception;
|
||||
OutputStream open();
|
||||
|
||||
void delete() throws Exception;
|
||||
void delete();
|
||||
|
||||
String getName();
|
||||
}
|
||||
@ -528,12 +522,12 @@ public abstract class NanoHTTPD {
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream open() throws Exception {
|
||||
public OutputStream open() {
|
||||
return fstream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() throws Exception {
|
||||
public void delete() {
|
||||
safeClose(fstream);
|
||||
file.delete();
|
||||
}
|
||||
@ -563,7 +557,7 @@ public abstract class NanoHTTPD {
|
||||
/**
|
||||
* Headers for the HTTP response. Use addHeader() to add lines.
|
||||
*/
|
||||
private Map<String, String> header = new ArrayMap<>();
|
||||
private final Map<String, String> header = new ArrayMap<>();
|
||||
/**
|
||||
* The request method that spawned this response.
|
||||
*/
|
||||
@ -616,7 +610,7 @@ public abstract class NanoHTTPD {
|
||||
/**
|
||||
* Sends given response to the socket.
|
||||
*/
|
||||
protected void send(OutputStream outputStream) {
|
||||
void send(OutputStream outputStream) {
|
||||
String mime = mimeType;
|
||||
SimpleDateFormat gmtFrmt = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
|
||||
gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
@ -661,13 +655,13 @@ public abstract class NanoHTTPD {
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendContentLengthHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header, int size) {
|
||||
void sendContentLengthHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header, int size) {
|
||||
if (!headerAlreadySent(header, "content-length")) {
|
||||
pw.print("Content-Length: "+ size +"\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendConnectionHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header) {
|
||||
void sendConnectionHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header) {
|
||||
if (!headerAlreadySent(header, "connection")) {
|
||||
pw.print("Connection: keep-alive\r\n");
|
||||
}
|
||||
@ -694,7 +688,7 @@ public abstract class NanoHTTPD {
|
||||
outputStream.write(buff, 0, read);
|
||||
outputStream.write(CRLF);
|
||||
}
|
||||
outputStream.write(String.format("0\r\n\r\n").getBytes());
|
||||
outputStream.write("0\r\n\r\n".getBytes());
|
||||
}
|
||||
|
||||
private void sendAsFixedLength(OutputStream outputStream, int pending) throws IOException {
|
||||
@ -844,7 +838,7 @@ public abstract class NanoHTTPD {
|
||||
public static final int BUFSIZE = 8192;
|
||||
private final TempFileManager tempFileManager;
|
||||
private final OutputStream outputStream;
|
||||
private PushbackInputStream inputStream;
|
||||
private final PushbackInputStream inputStream;
|
||||
private int splitbyte;
|
||||
private int rlen;
|
||||
private String uri;
|
||||
@ -1144,17 +1138,19 @@ public abstract class NanoHTTPD {
|
||||
|
||||
String value = "";
|
||||
if (item.get("content-type") == null) {
|
||||
StringBuilder tmp = new StringBuilder();
|
||||
while (mpline != null && !mpline.contains(boundary)) {
|
||||
mpline = in.readLine();
|
||||
if (mpline != null) {
|
||||
int d = mpline.indexOf(boundary);
|
||||
if (d == -1) {
|
||||
value += mpline;
|
||||
tmp.append(mpline);
|
||||
} else {
|
||||
value += mpline.substring(0, d - 2);
|
||||
tmp.append(mpline.substring(0, d - 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
value = tmp.toString();
|
||||
} else {
|
||||
if (boundarycount > bpositions.length) {
|
||||
throw new ResponseException(Response.Status.INTERNAL_ERROR, "Error processing request");
|
||||
@ -1326,7 +1322,9 @@ public abstract class NanoHTTPD {
|
||||
}
|
||||
|
||||
public static class Cookie {
|
||||
private String n, v, e;
|
||||
private final String n;
|
||||
private final String v;
|
||||
private final String e;
|
||||
|
||||
public Cookie(String name, String value, String expires) {
|
||||
n = name;
|
||||
@ -1366,8 +1364,8 @@ public abstract class NanoHTTPD {
|
||||
* @author LordFokas
|
||||
*/
|
||||
public class CookieHandler implements Iterable<String> {
|
||||
private ArrayMap<String, String> cookies = new ArrayMap<>();
|
||||
private ArrayList<Cookie> queue = new ArrayList<>();
|
||||
private final ArrayMap<String, String> cookies = new ArrayMap<>();
|
||||
private final ArrayList<Cookie> queue = new ArrayList<>();
|
||||
|
||||
public CookieHandler(Map<String, String> httpHeaders) {
|
||||
String raw = httpHeaders.get("cookie");
|
||||
|
@ -1,7 +1,7 @@
|
||||
package de.test.antennapod.util.syndication;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@ -9,6 +9,8 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;
|
||||
|
||||
/**
|
||||
* Test class for FeedDiscoverer
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@ public class AtomGenerator implements FeedGenerator{
|
||||
|
||||
private static final String NS_ATOM = "http://www.w3.org/2005/Atom";
|
||||
|
||||
public static final long FEATURE_USE_RFC3339LOCAL = 1;
|
||||
private static final long FEATURE_USE_RFC3339LOCAL = 1;
|
||||
|
||||
@Override
|
||||
public void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException {
|
||||
|
@ -1,10 +1,10 @@
|
||||
package de.test.antennapod.util.syndication.feedgenerator;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
|
||||
/**
|
||||
* Generates a machine-readable, platform-independent representation of a Feed object.
|
||||
*/
|
||||
@ -24,5 +24,5 @@ public interface FeedGenerator {
|
||||
* @param encoding The encoding to use. Must not be null.
|
||||
* @param flags Optional argument for enabling implementation-dependent features.
|
||||
*/
|
||||
public void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException;
|
||||
void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import java.io.IOException;
|
||||
/**
|
||||
* Utility methods for FeedGenerator
|
||||
*/
|
||||
public class GeneratorUtil {
|
||||
class GeneratorUtil {
|
||||
private GeneratorUtil(){}
|
||||
|
||||
public static void addPaymentLink(XmlSerializer xml, String paymentLink, boolean withNamespace) throws IOException {
|
||||
|
@ -1,14 +1,16 @@
|
||||
package de.test.antennapod.util.syndication.feedgenerator;
|
||||
|
||||
import android.util.Xml;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.util.DateUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.util.DateUtils;
|
||||
|
||||
/**
|
||||
* Creates RSS 2.0 feeds. See FeedGenerator for more information.
|
||||
*/
|
||||
|
@ -2,6 +2,6 @@ package de.danoeh.antennapod.config;
|
||||
|
||||
import de.danoeh.antennapod.core.CastCallbacks;
|
||||
|
||||
public class CastCallbackImpl implements CastCallbacks {
|
||||
class CastCallbackImpl implements CastCallbacks {
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
/**
|
||||
* Implements functions from PreferenceController that are flavor dependent.
|
||||
*/
|
||||
public class PreferenceControllerFlavorHelper {
|
||||
class PreferenceControllerFlavorHelper {
|
||||
|
||||
static void setupFlavoredUI(PreferenceController.PreferenceUI ui) {
|
||||
ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setEnabled(false);
|
||||
|
@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.danoeh.antennapod"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="1060402"
|
||||
android:versionName="1.6.4.2">
|
||||
android:versionCode="1070000"
|
||||
android:versionName="1.7.0">
|
||||
<!--
|
||||
Version code schema:
|
||||
"1.2.3-SNAPSHOT" -> 1020300
|
||||
@ -33,11 +33,12 @@
|
||||
|
||||
<application
|
||||
android:name="de.danoeh.antennapod.PodcastApp"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:label="@string/app_name"
|
||||
android:backupAgent=".core.backup.OpmlBackupAgent"
|
||||
android:restoreAnyVersion="true"
|
||||
android:logo="@drawable/ic_launcher">
|
||||
android:logo="@mipmap/ic_launcher">
|
||||
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||
android:resource="@drawable/ic_notification" />
|
||||
<meta-data
|
||||
@ -96,15 +97,6 @@
|
||||
android:name=".activity.DownloadAuthenticationActivity"
|
||||
android:launchMode="singleInstance"/>
|
||||
|
||||
<activity
|
||||
android:name=".activity.PreferenceActivityGingerbread"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/settings_label">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="de.danoeh.antennapod.activity.MainActivity"/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activity.PreferenceActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
@ -114,16 +106,25 @@
|
||||
android:value="de.danoeh.antennapod.activity.MainActivity"/>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".activity.FeedInfoActivity">
|
||||
<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=".service.PlayerWidgetService"
|
||||
android:name=".core.service.PlayerWidgetJobService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
</service>
|
||||
|
||||
<receiver android:name=".receiver.PlayerWidget">
|
||||
<receiver android:name=".core.receiver.PlayerWidget">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||
</intent-filter>
|
||||
@ -176,6 +177,13 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.ImportExportActivity"
|
||||
android:label="@string/import_export">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.OpmlImportFromPathActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
@ -224,7 +232,8 @@
|
||||
|
||||
<activity
|
||||
android:name=".activity.VideoplayerActivity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:screenOrientation="sensorLandscape">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
|
91
app/src/main/assets/LICENSE_SIL.txt
Normal file
91
app/src/main/assets/LICENSE_SIL.txt
Normal file
@ -0,0 +1,91 @@
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
Binary file not shown.
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 59 KiB |
@ -41,10 +41,8 @@ public class PodcastApp extends Application {
|
||||
.detectLeakedSqlLiteObjects()
|
||||
.penaltyLog()
|
||||
.penaltyDropBox();
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
builder.detectActivityLeaks();
|
||||
builder.detectLeakedClosableObjects();
|
||||
}
|
||||
builder.detectActivityLeaks();
|
||||
builder.detectLeakedClosableObjects();
|
||||
if(Build.VERSION.SDK_INT >= 16) {
|
||||
builder.detectLeakedRegistrationObjects();
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ import java.nio.charset.Charset;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import rx.Observable;
|
||||
import rx.Subscriber;
|
||||
import rx.Single;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
@ -34,10 +33,8 @@ public class AboutActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = AboutActivity.class.getSimpleName();
|
||||
|
||||
private WebView webview;
|
||||
private LinearLayout webviewContainer;
|
||||
private int depth = 0;
|
||||
|
||||
private WebView webView;
|
||||
private LinearLayout webViewContainer;
|
||||
private Subscription subscription;
|
||||
|
||||
@Override
|
||||
@ -46,28 +43,25 @@ public class AboutActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
setContentView(R.layout.about);
|
||||
webviewContainer = (LinearLayout) findViewById(R.id.webvContainer);
|
||||
webview = (WebView) findViewById(R.id.webvAbout);
|
||||
webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
|
||||
webViewContainer = (LinearLayout) findViewById(R.id.webViewContainer);
|
||||
webView = (WebView) findViewById(R.id.webViewAbout);
|
||||
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
|
||||
if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
|
||||
if (Build.VERSION.SDK_INT >= 11
|
||||
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
}
|
||||
webview.setBackgroundColor(Color.TRANSPARENT);
|
||||
webView.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
webview.setWebViewClient(new WebViewClient() {
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
if(url.startsWith("http")) {
|
||||
depth++;
|
||||
return false;
|
||||
} else {
|
||||
if (!url.startsWith("http")) {
|
||||
url = url.replace("file:///android_asset/", "");
|
||||
loadAsset(url);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
@ -75,69 +69,65 @@ public class AboutActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void loadAsset(String filename) {
|
||||
subscription = Observable.create(new Observable.OnSubscribe<String>() {
|
||||
@Override
|
||||
public void call(Subscriber<? super String> subscriber) {
|
||||
InputStream input = null;
|
||||
try {
|
||||
TypedArray res = AboutActivity.this.getTheme().obtainStyledAttributes(
|
||||
new int[] { android.R.attr.textColorPrimary });
|
||||
int colorResource = res.getColor(0, 0);
|
||||
String colorString = String.format("#%06X", 0xFFFFFF & colorResource);
|
||||
res.recycle();
|
||||
input = getAssets().open(filename);
|
||||
String webViewData = IOUtils.toString(input, Charset.defaultCharset());
|
||||
if(!webViewData.startsWith("<!DOCTYPE html>")) {
|
||||
//webViewData = webViewData.replace("\n\n", "</p><p>");
|
||||
webViewData = webViewData.replace("%", "%");
|
||||
webViewData =
|
||||
"<!DOCTYPE html>" +
|
||||
"<html>" +
|
||||
"<head>" +
|
||||
" <meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">" +
|
||||
" <style type=\"text/css\">" +
|
||||
" @font-face {" +
|
||||
" font-family: 'Roboto-Light';" +
|
||||
" src: url('file:///android_asset/Roboto-Light.ttf');" +
|
||||
" }" +
|
||||
" * {" +
|
||||
" color: %s;" +
|
||||
" font-family: roboto-Light;" +
|
||||
" font-size: 8pt;" +
|
||||
" }" +
|
||||
" </style>" +
|
||||
"</head><body><p>" + webViewData + "</p></body></html>";
|
||||
webViewData = webViewData.replace("\n", "<br/>");
|
||||
depth++;
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
webViewData = String.format(webViewData, colorString);
|
||||
subscriber.onNext(webViewData);
|
||||
} catch (IOException e) {
|
||||
subscriber.onError(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(input);
|
||||
}
|
||||
subscriber.onCompleted();
|
||||
}
|
||||
})
|
||||
subscription = Single.create(subscriber -> {
|
||||
InputStream input = null;
|
||||
try {
|
||||
TypedArray res = AboutActivity.this.getTheme().obtainStyledAttributes(
|
||||
new int[] { R.attr.about_screen_font_color, R.attr.about_screen_background,
|
||||
R.attr.about_screen_card_background, R.attr.about_screen_card_border});
|
||||
String fontColor = String.format("#%06X", 0xFFFFFF & res.getColor(0, 0));
|
||||
String backgroundColor = String.format("#%06X", 0xFFFFFF & res.getColor(1, 0));
|
||||
String cardBackground = String.format("#%06X", 0xFFFFFF & res.getColor(2, 0));
|
||||
String cardBorder = String.format("#%06X", 0xFFFFFF & res.getColor(3, 0));
|
||||
res.recycle();
|
||||
input = getAssets().open(filename);
|
||||
String webViewData = IOUtils.toString(input, Charset.defaultCharset());
|
||||
if (!webViewData.startsWith("<!DOCTYPE html>")) {
|
||||
webViewData = webViewData.replace("%", "%");
|
||||
webViewData =
|
||||
"<!DOCTYPE html>" +
|
||||
"<html>" +
|
||||
"<head>" +
|
||||
" <meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">" +
|
||||
" <style type=\"text/css\">" +
|
||||
" @font-face {" +
|
||||
" font-family: 'Roboto-Light';" +
|
||||
" src: url('file:///android_asset/Roboto-Light.ttf');" +
|
||||
" }" +
|
||||
" * {" +
|
||||
" color: @fontcolor@;" +
|
||||
" font-family: roboto-Light;" +
|
||||
" font-size: 8pt;" +
|
||||
" }" +
|
||||
" </style>" +
|
||||
"</head><body><p>" + webViewData + "</p></body></html>";
|
||||
webViewData = webViewData.replace("\n", "<br/>");
|
||||
}
|
||||
webViewData = webViewData.replace("@fontcolor@", fontColor);
|
||||
webViewData = webViewData.replace("@background@", backgroundColor);
|
||||
webViewData = webViewData.replace("@card_background@", cardBackground);
|
||||
webViewData = webViewData.replace("@card_border@", cardBorder);
|
||||
subscriber.onSuccess(webViewData);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
subscriber.onError(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(input);
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
webviewData ->
|
||||
webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html", "utf-8", "about:blank"),
|
||||
webViewData ->
|
||||
webView.loadDataWithBaseURL("file:///android_asset/", webViewData.toString(), "text/html", "utf-8", "file:///android_asset/" + filename.toString()),
|
||||
error -> Log.e(TAG, Log.getStackTraceString(error))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
Log.d(TAG, "depth: " + depth);
|
||||
if(depth == 1) {
|
||||
loadAsset("about.html");
|
||||
} else if(depth > 1) {
|
||||
webview.goBack();
|
||||
if (webView.canGoBack()) {
|
||||
webView.goBack();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
@ -159,9 +149,9 @@ public class AboutActivity extends AppCompatActivity {
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
if (webviewContainer != null && webview != null) {
|
||||
webviewContainer.removeAllViews();
|
||||
webview.destroy();
|
||||
if (webViewContainer != null && webView != null) {
|
||||
webViewContainer.removeAllViews();
|
||||
webView.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,41 +6,31 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
|
||||
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||
|
||||
/**
|
||||
* Activity for playing audio files.
|
||||
*/
|
||||
public class AudioplayerActivity extends MediaplayerInfoActivity {
|
||||
public static final String TAG = "AudioPlayerActivity";
|
||||
private static final String TAG = "AudioPlayerActivity";
|
||||
|
||||
private AtomicBoolean isSetup = new AtomicBoolean(false);
|
||||
private final AtomicBoolean isSetup = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
|
||||
Intent intent = getIntent();
|
||||
Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath());
|
||||
ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
|
||||
MediaType.AUDIO);
|
||||
Intent launchIntent = new Intent(this, PlaybackService.class);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
|
||||
true);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
|
||||
true);
|
||||
startService(launchIntent);
|
||||
playExternalMedia(getIntent(), MediaType.AUDIO);
|
||||
} else if (PlaybackService.isCasting()) {
|
||||
Intent intent = PlaybackService.getPlayerActivityIntent(this);
|
||||
if (!intent.getComponent().getClassName().equals(AudioplayerActivity.class.getName())) {
|
||||
if (intent.getComponent() != null &&
|
||||
!intent.getComponent().getClassName().equals(AudioplayerActivity.class.getName())) {
|
||||
saveCurrentFragment();
|
||||
finish();
|
||||
startActivity(intent);
|
||||
@ -95,7 +85,7 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
|
||||
UserPreferences.setPlaybackSpeed(String.valueOf(speed));
|
||||
}
|
||||
}
|
||||
String speedStr = String.format("%.2fx", speed);
|
||||
String speedStr = new DecimalFormat("0.00x").format(speed);
|
||||
butPlaybackSpeed.setText(speedStr);
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,9 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
* Activity for controlling the remote playback on a Cast device.
|
||||
*/
|
||||
public class CastplayerActivity extends MediaplayerInfoActivity {
|
||||
public static final String TAG = "CastPlayerActivity";
|
||||
private static final String TAG = "CastPlayerActivity";
|
||||
|
||||
private AtomicBoolean isSetup = new AtomicBoolean(false);
|
||||
private final AtomicBoolean isSetup = new AtomicBoolean(false);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -3,15 +3,14 @@ package de.danoeh.antennapod.activity;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.util.Log;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
||||
@ -23,8 +22,7 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
* Other arguments are optional.
|
||||
* The activity's result will be the same DownloadRequest with the entered username and password.
|
||||
*/
|
||||
public class DownloadAuthenticationActivity extends ActionBarActivity {
|
||||
private static final String TAG = "DownloadAuthenticationActivity";
|
||||
public class DownloadAuthenticationActivity extends AppCompatActivity {
|
||||
|
||||
/**
|
||||
* The download request object that contains information about the resource that requires a username and a password
|
||||
@ -36,47 +34,39 @@ public class DownloadAuthenticationActivity extends ActionBarActivity {
|
||||
*/
|
||||
public static final String ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL = "send_to_downloadrequester";
|
||||
|
||||
public static final String RESULT_REQUEST = "request";
|
||||
private static final String RESULT_REQUEST = "request";
|
||||
|
||||
private EditText etxtUsername;
|
||||
private EditText etxtPassword;
|
||||
private Button butConfirm;
|
||||
private Button butCancel;
|
||||
private TextView txtvDescription;
|
||||
|
||||
private DownloadRequest request;
|
||||
private boolean sendToDownloadRequester;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
getSupportActionBar().hide();
|
||||
setContentView(R.layout.download_authentication_activity);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
|
||||
setContentView(R.layout.download_authentication_activity);
|
||||
TextView txtvDescription = (TextView) findViewById(R.id.txtvDescription);
|
||||
etxtUsername = (EditText) findViewById(R.id.etxtUsername);
|
||||
etxtPassword = (EditText) findViewById(R.id.etxtPassword);
|
||||
butConfirm = (Button) findViewById(R.id.butConfirm);
|
||||
butCancel = (Button) findViewById(R.id.butCancel);
|
||||
txtvDescription = (TextView) findViewById(R.id.txtvDescription);
|
||||
Button butConfirm = (Button) findViewById(R.id.butConfirm);
|
||||
Button butCancel = (Button) findViewById(R.id.butCancel);
|
||||
|
||||
Validate.isTrue(getIntent().hasExtra(ARG_DOWNLOAD_REQUEST), "Download request missing");
|
||||
DownloadRequest request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST);
|
||||
boolean sendToDownloadRequester = getIntent().getBooleanExtra(ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL, false);
|
||||
|
||||
request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST);
|
||||
sendToDownloadRequester = getIntent().getBooleanExtra(ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL, false);
|
||||
String newDescription = txtvDescription.getText() + ":\n\n" + request.getTitle();
|
||||
txtvDescription.setText(newDescription);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
etxtUsername.setText(savedInstanceState.getString("username"));
|
||||
etxtPassword.setText(savedInstanceState.getString("password"));
|
||||
}
|
||||
|
||||
txtvDescription.setText(txtvDescription.getText() + ":\n\n" + request.getTitle());
|
||||
|
||||
butCancel.setOnClickListener(v -> {
|
||||
setResult(Activity.RESULT_CANCELED);
|
||||
finish();
|
||||
});
|
||||
|
||||
butConfirm.setOnClickListener(v -> {
|
||||
String username = etxtUsername.getText().toString();
|
||||
String password = etxtPassword.getText().toString();
|
||||
@ -87,11 +77,16 @@ public class DownloadAuthenticationActivity extends ActionBarActivity {
|
||||
setResult(Activity.RESULT_OK, result);
|
||||
|
||||
if (sendToDownloadRequester) {
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, "Sending request to DownloadRequester");
|
||||
DownloadRequester.getInstance().download(DownloadAuthenticationActivity.this, request);
|
||||
}
|
||||
finish();
|
||||
});
|
||||
|
||||
butCancel.setOnClickListener(v -> {
|
||||
setResult(Activity.RESULT_CANCELED);
|
||||
finish();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,51 +2,37 @@ package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.LightingColorFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedFilter;
|
||||
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import de.danoeh.antennapod.core.util.LangUtils;
|
||||
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
|
||||
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
@ -59,7 +45,6 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
|
||||
public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
|
||||
private static final String TAG = "FeedInfoActivity";
|
||||
private boolean autoDeleteChanged = false;
|
||||
private Feed feed;
|
||||
|
||||
private ImageView imgvCover;
|
||||
@ -70,15 +55,6 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
private TextView lblAuthor;
|
||||
private TextView txtvAuthor;
|
||||
private TextView txtvUrl;
|
||||
private EditText etxtUsername;
|
||||
private EditText etxtPassword;
|
||||
private EditText etxtFilterText;
|
||||
private RadioButton rdoFilterInclude;
|
||||
private RadioButton rdoFilterExclude;
|
||||
private CheckBox cbxAutoDownload;
|
||||
private CheckBox cbxKeepUpdated;
|
||||
private Spinner spnAutoDelete;
|
||||
private boolean filterInclude = true;
|
||||
|
||||
private Subscription subscription;
|
||||
|
||||
@ -88,56 +64,16 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
public void onClick(View v) {
|
||||
if(feed != null && feed.getDownload_url() != null) {
|
||||
String url = feed.getDownload_url();
|
||||
if (android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
ClipData clipData = ClipData.newPlainText(url, url);
|
||||
android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedInfoActivity.this
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(clipData);
|
||||
} else {
|
||||
android.text.ClipboardManager cm = (android.text.ClipboardManager) FeedInfoActivity.this
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setText(url);
|
||||
}
|
||||
ClipData clipData = ClipData.newPlainText(url, url);
|
||||
android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedInfoActivity.this
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(clipData);
|
||||
Toast t = Toast.makeText(FeedInfoActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT);
|
||||
t.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean authInfoChanged = false;
|
||||
|
||||
private TextWatcher authTextWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
authInfoChanged = true;
|
||||
}
|
||||
};
|
||||
|
||||
private boolean filterTextChanged = false;
|
||||
|
||||
private TextWatcher filterTextWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
filterTextChanged = true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
@ -148,28 +84,20 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
|
||||
imgvCover = (ImageView) findViewById(R.id.imgvCover);
|
||||
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
|
||||
TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor);
|
||||
ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground);
|
||||
findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
|
||||
findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
|
||||
// https://github.com/bumptech/glide/issues/529
|
||||
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
|
||||
|
||||
|
||||
txtvDescription = (TextView) findViewById(R.id.txtvDescription);
|
||||
lblLanguage = (TextView) findViewById(R.id.lblLanguage);
|
||||
txtvLanguage = (TextView) findViewById(R.id.txtvLanguage);
|
||||
lblAuthor = (TextView) findViewById(R.id.lblAuthor);
|
||||
txtvAuthor = (TextView) findViewById(R.id.txtvAuthor);
|
||||
txtvAuthor = (TextView) findViewById(R.id.txtvDetailsAuthor);
|
||||
txtvUrl = (TextView) findViewById(R.id.txtvUrl);
|
||||
cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
|
||||
cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated);
|
||||
spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete);
|
||||
etxtUsername = (EditText) findViewById(R.id.etxtUsername);
|
||||
etxtPassword = (EditText) findViewById(R.id.etxtPassword);
|
||||
etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText);
|
||||
rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include);
|
||||
rdoFilterInclude.setOnClickListener(v -> {
|
||||
filterInclude = true;
|
||||
filterTextChanged = true;
|
||||
});
|
||||
rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude);
|
||||
rdoFilterExclude.setOnClickListener(v -> {
|
||||
filterInclude = false;
|
||||
filterTextChanged = true;
|
||||
});
|
||||
|
||||
txtvUrl.setOnClickListener(copyUrlToClipboard);
|
||||
|
||||
@ -185,7 +113,6 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
Log.d(TAG, "Language is " + feed.getLanguage());
|
||||
Log.d(TAG, "Author is " + feed.getAuthor());
|
||||
Log.d(TAG, "URL is " + feed.getDownload_url());
|
||||
FeedPreferences prefs = feed.getPreferences();
|
||||
Glide.with(FeedInfoActivity.this)
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
@ -194,6 +121,14 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(imgvCover);
|
||||
Glide.with(FeedInfoActivity.this)
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.image_readability_tint)
|
||||
.error(R.color.image_readability_tint)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.transform(new FastBlurTransformation(FeedInfoActivity.this))
|
||||
.dontAnimate()
|
||||
.into(imgvBackground);
|
||||
|
||||
txtvTitle.setText(feed.getTitle());
|
||||
|
||||
@ -211,6 +146,7 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
|
||||
if (!TextUtils.isEmpty(feed.getAuthor())) {
|
||||
txtvAuthor.setText(feed.getAuthor());
|
||||
txtvAuthorHeader.setText(feed.getAuthor());
|
||||
} else {
|
||||
lblAuthor.setVisibility(View.GONE);
|
||||
txtvAuthor.setVisibility(View.GONE);
|
||||
@ -224,113 +160,13 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}");
|
||||
Iconify.addIcons(txtvUrl);
|
||||
|
||||
cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
|
||||
cbxAutoDownload.setChecked(prefs.getAutoDownload());
|
||||
cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> {
|
||||
feed.getPreferences().setAutoDownload(checked);
|
||||
feed.savePreferences();
|
||||
updateAutoDownloadSettings();
|
||||
ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this,
|
||||
feed, checked);
|
||||
dialog.createNewDialog().show();
|
||||
});
|
||||
cbxKeepUpdated.setChecked(prefs.getKeepUpdated());
|
||||
cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> {
|
||||
feed.getPreferences().setKeepUpdated(checked);
|
||||
feed.savePreferences();
|
||||
});
|
||||
spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
||||
FeedPreferences.AutoDeleteAction auto_delete_action;
|
||||
switch (parent.getSelectedItemPosition()) {
|
||||
case 0:
|
||||
auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL;
|
||||
break;
|
||||
case 1:
|
||||
auto_delete_action = FeedPreferences.AutoDeleteAction.YES;
|
||||
break;
|
||||
case 2:
|
||||
auto_delete_action = FeedPreferences.AutoDeleteAction.NO;
|
||||
break;
|
||||
default: // TODO - add exceptions here
|
||||
return;
|
||||
}
|
||||
feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p
|
||||
autoDeleteChanged = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
// Another interface callback
|
||||
}
|
||||
});
|
||||
spnAutoDelete.setSelection(prefs.getAutoDeleteAction().ordinal());
|
||||
|
||||
etxtUsername.setText(prefs.getUsername());
|
||||
etxtPassword.setText(prefs.getPassword());
|
||||
|
||||
etxtUsername.addTextChangedListener(authTextWatcher);
|
||||
etxtPassword.addTextChangedListener(authTextWatcher);
|
||||
|
||||
FeedFilter filter = prefs.getFilter();
|
||||
if (filter.includeOnly()) {
|
||||
etxtFilterText.setText(filter.getIncludeFilter());
|
||||
rdoFilterInclude.setChecked(true);
|
||||
rdoFilterExclude.setChecked(false);
|
||||
filterInclude = true;
|
||||
} else if (filter.excludeOnly()) {
|
||||
etxtFilterText.setText(filter.getExcludeFilter());
|
||||
rdoFilterInclude.setChecked(false);
|
||||
rdoFilterExclude.setChecked(true);
|
||||
filterInclude = false;
|
||||
} else {
|
||||
Log.d(TAG, "No filter set");
|
||||
rdoFilterInclude.setChecked(false);
|
||||
rdoFilterExclude.setChecked(false);
|
||||
etxtFilterText.setText("");
|
||||
}
|
||||
etxtFilterText.addTextChangedListener(filterTextWatcher);
|
||||
|
||||
supportInvalidateOptionsMenu();
|
||||
updateAutoDownloadSettings();
|
||||
}, error -> {
|
||||
Log.d(TAG, Log.getStackTraceString(error));
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (feed != null) {
|
||||
FeedPreferences prefs = feed.getPreferences();
|
||||
if (authInfoChanged) {
|
||||
Log.d(TAG, "Auth info changed, saving credentials");
|
||||
prefs.setUsername(etxtUsername.getText().toString());
|
||||
prefs.setPassword(etxtPassword.getText().toString());
|
||||
}
|
||||
if (filterTextChanged) {
|
||||
Log.d(TAG, "Filter info changed, saving...");
|
||||
String filterText = etxtFilterText.getText().toString();
|
||||
String includeString = "";
|
||||
String excludeString = "";
|
||||
if (filterInclude) {
|
||||
includeString = filterText;
|
||||
} else {
|
||||
excludeString = filterText;
|
||||
}
|
||||
prefs.setFilter(new FeedFilter(includeString, excludeString));
|
||||
}
|
||||
if (authInfoChanged || autoDeleteChanged || filterTextChanged) {
|
||||
DBWriter.setFeedPreferences(prefs);
|
||||
}
|
||||
authInfoChanged = false;
|
||||
autoDeleteChanged = false;
|
||||
filterTextChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
@ -375,34 +211,4 @@ public class FeedInfoActivity extends AppCompatActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAutoDownloadSettings() {
|
||||
if (feed != null && feed.getPreferences() != null) {
|
||||
boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload();
|
||||
rdoFilterInclude.setEnabled(enabled);
|
||||
rdoFilterExclude.setEnabled(enabled);
|
||||
etxtFilterText.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private class ApplyToEpisodesDialog extends ConfirmationDialog {
|
||||
|
||||
private final Feed feed;
|
||||
private final boolean autoDownload;
|
||||
|
||||
ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) {
|
||||
super(context, R.string.auto_download_apply_to_items_title,
|
||||
R.string.auto_download_apply_to_items_message);
|
||||
this.feed = feed;
|
||||
this.autoDownload = autoDownload;
|
||||
setPositiveText(R.string.yes);
|
||||
setNegativeText(R.string.no);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
DBWriter.setFeedsItemsAutoDownload(feed, autoDownload);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,370 @@
|
||||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.LightingColorFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import com.bumptech.glide.Glide;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedFilter;
|
||||
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Displays information about a feed.
|
||||
*/
|
||||
public class FeedSettingsActivity extends AppCompatActivity {
|
||||
|
||||
public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
|
||||
private static final String TAG = "FeedSettingsActivity";
|
||||
private boolean autoDeleteChanged = false;
|
||||
private Feed feed;
|
||||
|
||||
private ImageView imgvCover;
|
||||
private TextView txtvTitle;
|
||||
private EditText etxtUsername;
|
||||
private EditText etxtPassword;
|
||||
private EditText etxtFilterText;
|
||||
private RadioButton rdoFilterInclude;
|
||||
private RadioButton rdoFilterExclude;
|
||||
private CheckBox cbxAutoDownload;
|
||||
private CheckBox cbxKeepUpdated;
|
||||
private Spinner spnAutoDelete;
|
||||
private boolean filterInclude = true;
|
||||
|
||||
private Subscription subscription;
|
||||
|
||||
|
||||
private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(feed != null && feed.getDownload_url() != null) {
|
||||
String url = feed.getDownload_url();
|
||||
ClipData clipData = ClipData.newPlainText(url, url);
|
||||
android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedSettingsActivity.this
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setPrimaryClip(clipData);
|
||||
Toast t = Toast.makeText(FeedSettingsActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT);
|
||||
t.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean authInfoChanged = false;
|
||||
|
||||
private final TextWatcher authTextWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
authInfoChanged = true;
|
||||
}
|
||||
};
|
||||
|
||||
private boolean filterTextChanged = false;
|
||||
|
||||
private final TextWatcher filterTextWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
filterTextChanged = true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.feedsettings);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1);
|
||||
|
||||
imgvCover = (ImageView) findViewById(R.id.imgvCover);
|
||||
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
|
||||
TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor);
|
||||
ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground);
|
||||
findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
|
||||
findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
|
||||
// https://github.com/bumptech/glide/issues/529
|
||||
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
|
||||
|
||||
cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
|
||||
cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated);
|
||||
spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete);
|
||||
etxtUsername = (EditText) findViewById(R.id.etxtUsername);
|
||||
etxtPassword = (EditText) findViewById(R.id.etxtPassword);
|
||||
etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText);
|
||||
rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include);
|
||||
rdoFilterInclude.setOnClickListener(v -> {
|
||||
filterInclude = true;
|
||||
filterTextChanged = true;
|
||||
});
|
||||
rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude);
|
||||
rdoFilterExclude.setOnClickListener(v -> {
|
||||
filterInclude = false;
|
||||
filterTextChanged = true;
|
||||
});
|
||||
|
||||
subscription = Observable.fromCallable(()-> DBReader.getFeed(feedId))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
if (result == null) {
|
||||
Log.e(TAG, "Activity was started with invalid arguments");
|
||||
finish();
|
||||
}
|
||||
feed = result;
|
||||
FeedPreferences prefs = feed.getPreferences();
|
||||
Glide.with(FeedSettingsActivity.this)
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(imgvCover);
|
||||
Glide.with(FeedSettingsActivity.this)
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.image_readability_tint)
|
||||
.error(R.color.image_readability_tint)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.transform(new FastBlurTransformation(FeedSettingsActivity.this))
|
||||
.dontAnimate()
|
||||
.into(imgvBackground);
|
||||
|
||||
txtvTitle.setText(feed.getTitle());
|
||||
|
||||
if (!TextUtils.isEmpty(feed.getAuthor())) {
|
||||
txtvAuthorHeader.setText(feed.getAuthor());
|
||||
}
|
||||
|
||||
cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
|
||||
cbxAutoDownload.setChecked(prefs.getAutoDownload());
|
||||
cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> {
|
||||
feed.getPreferences().setAutoDownload(checked);
|
||||
feed.savePreferences();
|
||||
updateAutoDownloadSettings();
|
||||
ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedSettingsActivity.this,
|
||||
feed, checked);
|
||||
dialog.createNewDialog().show();
|
||||
});
|
||||
cbxKeepUpdated.setChecked(prefs.getKeepUpdated());
|
||||
cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> {
|
||||
feed.getPreferences().setKeepUpdated(checked);
|
||||
feed.savePreferences();
|
||||
});
|
||||
spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
|
||||
FeedPreferences.AutoDeleteAction auto_delete_action;
|
||||
switch (parent.getSelectedItemPosition()) {
|
||||
case 0:
|
||||
auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL;
|
||||
break;
|
||||
case 1:
|
||||
auto_delete_action = FeedPreferences.AutoDeleteAction.YES;
|
||||
break;
|
||||
case 2:
|
||||
auto_delete_action = FeedPreferences.AutoDeleteAction.NO;
|
||||
break;
|
||||
default: // TODO - add exceptions here
|
||||
return;
|
||||
}
|
||||
feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p
|
||||
autoDeleteChanged = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
// Another interface callback
|
||||
}
|
||||
});
|
||||
spnAutoDelete.setSelection(prefs.getAutoDeleteAction().ordinal());
|
||||
|
||||
etxtUsername.setText(prefs.getUsername());
|
||||
etxtPassword.setText(prefs.getPassword());
|
||||
|
||||
etxtUsername.addTextChangedListener(authTextWatcher);
|
||||
etxtPassword.addTextChangedListener(authTextWatcher);
|
||||
|
||||
FeedFilter filter = prefs.getFilter();
|
||||
if (filter.includeOnly()) {
|
||||
etxtFilterText.setText(filter.getIncludeFilter());
|
||||
rdoFilterInclude.setChecked(true);
|
||||
rdoFilterExclude.setChecked(false);
|
||||
filterInclude = true;
|
||||
} else if (filter.excludeOnly()) {
|
||||
etxtFilterText.setText(filter.getExcludeFilter());
|
||||
rdoFilterInclude.setChecked(false);
|
||||
rdoFilterExclude.setChecked(true);
|
||||
filterInclude = false;
|
||||
} else {
|
||||
Log.d(TAG, "No filter set");
|
||||
rdoFilterInclude.setChecked(false);
|
||||
rdoFilterExclude.setChecked(false);
|
||||
etxtFilterText.setText("");
|
||||
}
|
||||
etxtFilterText.addTextChangedListener(filterTextWatcher);
|
||||
|
||||
supportInvalidateOptionsMenu();
|
||||
updateAutoDownloadSettings();
|
||||
}, error -> {
|
||||
Log.d(TAG, Log.getStackTraceString(error));
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (feed != null) {
|
||||
FeedPreferences prefs = feed.getPreferences();
|
||||
if (authInfoChanged) {
|
||||
Log.d(TAG, "Auth info changed, saving credentials");
|
||||
prefs.setUsername(etxtUsername.getText().toString());
|
||||
prefs.setPassword(etxtPassword.getText().toString());
|
||||
}
|
||||
if (filterTextChanged) {
|
||||
Log.d(TAG, "Filter info changed, saving...");
|
||||
String filterText = etxtFilterText.getText().toString();
|
||||
String includeString = "";
|
||||
String excludeString = "";
|
||||
if (filterInclude) {
|
||||
includeString = filterText;
|
||||
} else {
|
||||
excludeString = filterText;
|
||||
}
|
||||
prefs.setFilter(new FeedFilter(includeString, excludeString));
|
||||
}
|
||||
if (authInfoChanged || autoDeleteChanged || filterTextChanged) {
|
||||
DBWriter.setFeedPreferences(prefs);
|
||||
}
|
||||
authInfoChanged = false;
|
||||
autoDeleteChanged = false;
|
||||
filterTextChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.feedinfo, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
menu.findItem(R.id.support_item).setVisible(
|
||||
feed != null && feed.getPaymentLink() != null);
|
||||
menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null);
|
||||
menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null &&
|
||||
IntentUtils.isCallable(this, new Intent(Intent.ACTION_VIEW, Uri.parse(feed.getLink()))));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
default:
|
||||
try {
|
||||
return FeedMenuHandler.onOptionsItemClicked(this, item, feed);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
DownloadRequestErrorDialogCreator.newRequestErrorDialog(this,
|
||||
e.getMessage());
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAutoDownloadSettings() {
|
||||
if (feed != null && feed.getPreferences() != null) {
|
||||
boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload();
|
||||
rdoFilterInclude.setEnabled(enabled);
|
||||
rdoFilterExclude.setEnabled(enabled);
|
||||
etxtFilterText.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ApplyToEpisodesDialog extends ConfirmationDialog {
|
||||
|
||||
private final Feed feed;
|
||||
private final boolean autoDownload;
|
||||
|
||||
ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) {
|
||||
super(context, R.string.auto_download_apply_to_items_title,
|
||||
R.string.auto_download_apply_to_items_message);
|
||||
this.feed = feed;
|
||||
this.autoDownload = autoDownload;
|
||||
setPositiveText(R.string.yes);
|
||||
setNegativeText(R.string.no);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
DBWriter.setFeedsItemsAutoDownload(feed, autoDownload);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -4,7 +4,7 @@ package de.danoeh.antennapod.activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@ -18,11 +18,10 @@ import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.util.flattr.FlattrUtils;
|
||||
import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
|
||||
/** Guides the user through the authentication process */
|
||||
|
||||
public class FlattrAuthActivity extends ActionBarActivity {
|
||||
public class FlattrAuthActivity extends AppCompatActivity {
|
||||
private static final String TAG = "FlattrAuthActivity";
|
||||
|
||||
private TextView txtvExplanation;
|
||||
@ -104,7 +103,7 @@ public class FlattrAuthActivity extends ActionBarActivity {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
if (authSuccessful) {
|
||||
Intent intent = new Intent(this, PreferenceController.getPreferenceActivity());
|
||||
Intent intent = new Intent(this, PreferenceActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
} else {
|
||||
|
@ -0,0 +1,188 @@
|
||||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.MenuItem;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
/**
|
||||
* Displays the 'import/export' screen
|
||||
*/
|
||||
public class ImportExportActivity extends AppCompatActivity {
|
||||
private static final int REQUEST_CODE_RESTORE = 43;
|
||||
private static final int REQUEST_CODE_BACKUP_DOCUMENT = 44;
|
||||
private static final String EXPORT_FILENAME = "AntennaPodBackup.db";
|
||||
private static final String TAG = ImportExportActivity.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
setContentView(R.layout.import_export_activity);
|
||||
|
||||
findViewById(R.id.button_export).setOnClickListener(view -> backup());
|
||||
findViewById(R.id.button_import).setOnClickListener(view -> restore());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void backup() {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
.setType("application/x-sqlite3")
|
||||
.putExtra(Intent.EXTRA_TITLE, EXPORT_FILENAME);
|
||||
|
||||
startActivityForResult(intent, REQUEST_CODE_BACKUP_DOCUMENT);
|
||||
} else {
|
||||
try {
|
||||
File sd = Environment.getExternalStorageDirectory();
|
||||
File backupDB = new File(sd, EXPORT_FILENAME);
|
||||
writeBackupTo(new FileOutputStream(backupDB));
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void restore() {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.setType("*/*");
|
||||
startActivityForResult(intent, REQUEST_CODE_RESTORE);
|
||||
} else {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("*/*");
|
||||
startActivityForResult(Intent.createChooser(intent,
|
||||
getString(R.string.import_select_file)), REQUEST_CODE_RESTORE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
||||
if (resultCode != RESULT_OK || resultData == null) {
|
||||
return;
|
||||
}
|
||||
Uri uri = resultData.getData();
|
||||
|
||||
if (requestCode == REQUEST_CODE_RESTORE) {
|
||||
restoreFrom(uri);
|
||||
} else if (requestCode == REQUEST_CODE_BACKUP_DOCUMENT) {
|
||||
backupToDocument(uri);
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreFrom(Uri inputUri) {
|
||||
File currentDB = getDatabasePath(PodDBAdapter.DATABASE_NAME);
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = getContentResolver().openInputStream(inputUri);
|
||||
FileUtils.copyInputStreamToFile(inputStream, currentDB);
|
||||
displayImportSuccessDialog();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
private void displayImportSuccessDialog() {
|
||||
AlertDialog.Builder d = new AlertDialog.Builder(ImportExportActivity.this);
|
||||
d.setMessage(R.string.import_ok);
|
||||
d.setCancelable(false);
|
||||
d.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
||||
Intent intent = new Intent(getApplicationContext(), SplashActivity.class);
|
||||
ComponentName cn = intent.getComponent();
|
||||
Intent mainIntent = Intent.makeRestartActivityTask(cn);
|
||||
startActivity(mainIntent);
|
||||
});
|
||||
d.show();
|
||||
}
|
||||
|
||||
private void backupToDocument(Uri uri) {
|
||||
ParcelFileDescriptor pfd = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
pfd = getContentResolver().openFileDescriptor(uri, "w");
|
||||
fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
|
||||
writeBackupTo(fileOutputStream);
|
||||
|
||||
Snackbar.make(findViewById(R.id.import_export_layout),
|
||||
R.string.export_ok, Snackbar.LENGTH_SHORT).show();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fileOutputStream);
|
||||
|
||||
if (pfd != null) {
|
||||
try {
|
||||
pfd.close();
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "Unable to close ParcelFileDescriptor");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBackupTo(FileOutputStream outFileStream) {
|
||||
FileChannel src = null;
|
||||
FileChannel dst = null;
|
||||
try {
|
||||
File currentDB = getDatabasePath(PodDBAdapter.DATABASE_NAME);
|
||||
|
||||
if (currentDB.exists()) {
|
||||
src = new FileInputStream(currentDB).getChannel();
|
||||
dst = outFileStream.getChannel();
|
||||
dst.transferFrom(src, 0, src.size());
|
||||
|
||||
Snackbar.make(findViewById(R.id.import_export_layout),
|
||||
R.string.export_ok, Snackbar.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Snackbar.make(findViewById(R.id.import_export_layout),
|
||||
"Can not access current database", Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
|
||||
} finally {
|
||||
IOUtils.closeQuietly(src);
|
||||
IOUtils.closeQuietly(dst);
|
||||
}
|
||||
}
|
||||
}
|
@ -30,6 +30,9 @@ import android.widget.ListView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
|
||||
import de.danoeh.antennapod.core.event.ServiceEvent;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
@ -64,7 +67,6 @@ import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
|
||||
import de.danoeh.antennapod.fragment.QueueFragment;
|
||||
import de.danoeh.antennapod.fragment.SubscriptionFragment;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
import de.greenrobot.event.EventBus;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
@ -83,7 +85,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
|
||||
public static final String PREF_NAME = "MainActivityPrefs";
|
||||
public static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
|
||||
public static final String PREF_LAST_FRAGMENT_TAG = "prefMainActivityLastFragmentTag";
|
||||
private static final String PREF_LAST_FRAGMENT_TAG = "prefMainActivityLastFragmentTag";
|
||||
|
||||
public static final String EXTRA_NAV_TYPE = "nav_type";
|
||||
public static final String EXTRA_NAV_INDEX = "nav_index";
|
||||
@ -91,8 +93,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
|
||||
public static final String EXTRA_FEED_ID = "fragment_feed_id";
|
||||
|
||||
public static final String SAVE_BACKSTACK_COUNT = "backstackCount";
|
||||
public static final String SAVE_TITLE = "title";
|
||||
private static final String SAVE_BACKSTACK_COUNT = "backstackCount";
|
||||
private static final String SAVE_TITLE = "title";
|
||||
|
||||
public static final String[] NAV_DRAWER_TAGS = {
|
||||
QueueFragment.TAG,
|
||||
@ -173,7 +175,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
|
||||
findViewById(R.id.nav_settings).setOnClickListener(v -> {
|
||||
drawerLayout.closeDrawer(navDrawer);
|
||||
startActivity(new Intent(MainActivity.this, PreferenceController.getPreferenceActivity()));
|
||||
startActivity(new Intent(MainActivity.this, PreferenceActivity.class));
|
||||
});
|
||||
|
||||
FragmentTransaction transaction = fm.beginTransaction();
|
||||
@ -201,6 +203,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
transaction.commit();
|
||||
|
||||
checkFirstLaunch();
|
||||
NotificationUtils.createChannels(this);
|
||||
UserPreferences.restartUpdateAlarm(false);
|
||||
}
|
||||
|
||||
private void saveLastNavFragment(String tag) {
|
||||
@ -236,7 +240,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
}
|
||||
}
|
||||
|
||||
public void showDrawerPreferencesDialog() {
|
||||
private void showDrawerPreferencesDialog() {
|
||||
final List<String> hiddenDrawerItems = UserPreferences.getHiddenDrawerItems();
|
||||
String[] navLabels = new String[NAV_DRAWER_TAGS.length];
|
||||
final boolean[] checked = new boolean[NAV_DRAWER_TAGS.length];
|
||||
@ -270,7 +274,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
return (navDrawerData != null) ? navDrawerData.feeds : null;
|
||||
}
|
||||
|
||||
public void loadFragment(int index, Bundle args) {
|
||||
private void loadFragment(int index, Bundle args) {
|
||||
Log.d(TAG, "loadFragment(index: " + index + ", args: " + args + ")");
|
||||
if (index < navAdapter.getSubscriptionOffset()) {
|
||||
String tag = navAdapter.getTags().get(index);
|
||||
@ -399,7 +403,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
}
|
||||
}
|
||||
|
||||
private AdapterView.OnItemClickListener navListClickListener = new AdapterView.OnItemClickListener() {
|
||||
private final AdapterView.OnItemClickListener navListClickListener = new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
int viewType = parent.getAdapter().getItemViewType(position);
|
||||
@ -410,7 +414,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
}
|
||||
};
|
||||
|
||||
private AdapterView.OnItemLongClickListener newListLongClickListener = new AdapterView.OnItemLongClickListener() {
|
||||
private final AdapterView.OnItemLongClickListener newListLongClickListener = new AdapterView.OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if(position < navAdapter.getTags().size()) {
|
||||
@ -573,10 +577,29 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
|
||||
switch(item.getItemId()) {
|
||||
case R.id.mark_all_seen_item:
|
||||
DBWriter.markFeedSeen(feed.getId());
|
||||
ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(this,
|
||||
R.string.mark_all_seen_label,
|
||||
R.string.mark_all_seen_confirmation_msg) {
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
DBWriter.markFeedSeen(feed.getId());
|
||||
}
|
||||
};
|
||||
markAllSeenConfirmationDialog.createNewDialog().show();
|
||||
return true;
|
||||
case R.id.mark_all_read_item:
|
||||
DBWriter.markFeedRead(feed.getId());
|
||||
ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(this,
|
||||
R.string.mark_all_read_label,
|
||||
R.string.mark_all_read_confirmation_msg) {
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
DBWriter.markFeedRead(feed.getId());
|
||||
}
|
||||
};
|
||||
markAllReadConfirmationDialog.createNewDialog().show();
|
||||
return true;
|
||||
case R.id.rename_item:
|
||||
new RenameFeedDialog(this, feed).show();
|
||||
@ -605,8 +628,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
remover.skipOnCompletion = true;
|
||||
int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
|
||||
if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
|
||||
sendBroadcast(new Intent(
|
||||
PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
|
||||
IntentUtils.sendLocalBroadcast(MainActivity.this, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
|
||||
}
|
||||
}
|
||||
remover.executeAsync();
|
||||
@ -631,7 +653,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
private DBReader.NavDrawerData navDrawerData;
|
||||
private int selectedNavListIndex = 0;
|
||||
|
||||
private NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
|
||||
private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (navDrawerData != null) {
|
||||
@ -721,6 +743,15 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
loadData();
|
||||
}
|
||||
|
||||
public void onEventMainThread(ServiceEvent event) {
|
||||
Log.d(TAG, "onEvent(" + event + ")");
|
||||
switch(event.action) {
|
||||
case SERVICE_STARTED:
|
||||
externalPlayerFragment.connectToPlaybackService();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onEventMainThread(ProgressEvent event) {
|
||||
Log.d(TAG, "onEvent(" + event + ")");
|
||||
switch(event.action) {
|
||||
@ -744,14 +775,12 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
||||
View parentLayout = findViewById(R.id.drawer_layout);
|
||||
Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT);
|
||||
if(event.action != null) {
|
||||
snackbar.setAction(getString(R.string.undo), v -> {
|
||||
event.action.run();
|
||||
});
|
||||
snackbar.setAction(getString(R.string.undo), v -> event.action.run());
|
||||
}
|
||||
snackbar.show();
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
|
@ -1,9 +1,11 @@
|
||||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
@ -11,6 +13,9 @@ import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
@ -33,21 +38,28 @@ import com.joanzapata.iconify.fonts.FontAwesomeIcons;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.event.ServiceEvent;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.Converter;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.core.util.Flavors;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import de.danoeh.antennapod.core.util.ShareUtils;
|
||||
import de.danoeh.antennapod.core.util.StorageUtils;
|
||||
import de.danoeh.antennapod.core.util.Supplier;
|
||||
import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
|
||||
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
|
||||
import de.danoeh.antennapod.core.util.playback.MediaPlayerError;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
||||
import de.danoeh.antennapod.dialog.SleepTimerDialog;
|
||||
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||
import rx.Observable;
|
||||
@ -65,20 +77,21 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
private static final String TAG = "MediaplayerActivity";
|
||||
private static final String PREFS = "MediaPlayerActivityPreferences";
|
||||
private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
|
||||
private static final int REQUEST_CODE_STORAGE = 42;
|
||||
|
||||
protected PlaybackController controller;
|
||||
PlaybackController controller;
|
||||
|
||||
protected TextView txtvPosition;
|
||||
protected TextView txtvLength;
|
||||
protected SeekBar sbPosition;
|
||||
protected ImageButton butRev;
|
||||
protected TextView txtvRev;
|
||||
protected ImageButton butPlay;
|
||||
protected ImageButton butFF;
|
||||
protected TextView txtvFF;
|
||||
protected ImageButton butSkip;
|
||||
private TextView txtvPosition;
|
||||
private TextView txtvLength;
|
||||
SeekBar sbPosition;
|
||||
private ImageButton butRev;
|
||||
private TextView txtvRev;
|
||||
private ImageButton butPlay;
|
||||
private ImageButton butFF;
|
||||
private TextView txtvFF;
|
||||
private ImageButton butSkip;
|
||||
|
||||
protected boolean showTimeLeft = false;
|
||||
private boolean showTimeLeft = false;
|
||||
|
||||
private boolean isFavorite = false;
|
||||
|
||||
@ -183,31 +196,31 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
};
|
||||
}
|
||||
|
||||
protected static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
|
||||
private static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
|
||||
return activity.txtvFF;
|
||||
}
|
||||
protected static TextView getTxtvRevFromActivity(MediaplayerActivity activity) {
|
||||
private static TextView getTxtvRevFromActivity(MediaplayerActivity activity) {
|
||||
return activity.txtvRev;
|
||||
}
|
||||
|
||||
protected void onSetSpeedAbilityChanged() {
|
||||
private void onSetSpeedAbilityChanged() {
|
||||
Log.d(TAG, "onSetSpeedAbilityChanged()");
|
||||
updatePlaybackSpeedButton();
|
||||
}
|
||||
|
||||
protected void onPlaybackSpeedChange() {
|
||||
private void onPlaybackSpeedChange() {
|
||||
updatePlaybackSpeedButtonText();
|
||||
}
|
||||
|
||||
protected void onServiceQueried() {
|
||||
private void onServiceQueried() {
|
||||
supportInvalidateOptionsMenu();
|
||||
}
|
||||
|
||||
protected void chooseTheme() {
|
||||
void chooseTheme() {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
}
|
||||
|
||||
protected void setScreenOn(boolean enable) {
|
||||
void setScreenOn(boolean enable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -224,9 +237,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
if(controller != null) {
|
||||
controller.reinitServiceIfPaused();
|
||||
controller.pause();
|
||||
if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
|
||||
if (controller != null) {
|
||||
controller.reinitServiceIfPaused();
|
||||
controller.pause();
|
||||
}
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
@ -248,7 +263,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
*/
|
||||
protected abstract void onBufferEnd();
|
||||
|
||||
protected void onBufferUpdate(float progress) {
|
||||
private void onBufferUpdate(float progress) {
|
||||
if (sbPosition != null) {
|
||||
sbPosition.setSecondaryProgress((int) progress * sbPosition.getMax());
|
||||
}
|
||||
@ -257,7 +272,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
/**
|
||||
* Current screen orientation.
|
||||
*/
|
||||
protected int orientation;
|
||||
private int orientation;
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
@ -266,6 +281,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
controller.release();
|
||||
}
|
||||
controller = newPlaybackController();
|
||||
setupGUI();
|
||||
loadMediaInfo();
|
||||
onPositionObserverUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -316,11 +334,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
((FeedMedia) media).getItem().getFlattrStatus().flattrable()
|
||||
);
|
||||
|
||||
boolean hasWebsiteLink = media != null && media.getWebsiteLink() != null;
|
||||
boolean hasWebsiteLink = ( getWebsiteLinkWithFallback(media) != null );
|
||||
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink);
|
||||
|
||||
boolean isItemAndHasLink = isFeedMedia &&
|
||||
((FeedMedia) media).getItem() != null && ((FeedMedia) media).getItem().getLink() != null;
|
||||
ShareUtils.hasLinkToShare(((FeedMedia) media).getItem());
|
||||
menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink);
|
||||
menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink);
|
||||
|
||||
@ -368,7 +386,17 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
| Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
|
||||
View cover = findViewById(R.id.imgvCover);
|
||||
if (cover != null && Build.VERSION.SDK_INT >= 16) {
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat.
|
||||
makeSceneTransitionAnimation(MediaplayerActivity.this,
|
||||
cover, "coverTransition");
|
||||
startActivity(intent, options.toBundle());
|
||||
} else {
|
||||
startActivity(intent);
|
||||
}
|
||||
finish();
|
||||
return true;
|
||||
} else {
|
||||
if (media != null) {
|
||||
@ -546,7 +574,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
});
|
||||
break;
|
||||
case R.id.visit_website_item:
|
||||
Uri uri = Uri.parse(media.getWebsiteLink());
|
||||
Uri uri = Uri.parse(getWebsiteLinkWithFallback(media));
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
||||
break;
|
||||
case R.id.support_item:
|
||||
@ -589,16 +617,37 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
}
|
||||
}
|
||||
|
||||
private static String getWebsiteLinkWithFallback(Playable media) {
|
||||
if (media == null) {
|
||||
return null;
|
||||
} else if (media.getWebsiteLink() != null) {
|
||||
return media.getWebsiteLink();
|
||||
} else if (media instanceof FeedMedia) {
|
||||
return FeedItemUtil.getLinkWithFallback(((FeedMedia)media).getItem());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Log.d(TAG, "onResume()");
|
||||
StorageUtils.checkStorageAvailability(this);
|
||||
if(controller != null) {
|
||||
if (controller != null) {
|
||||
controller.init();
|
||||
}
|
||||
}
|
||||
|
||||
public void onEventMainThread(ServiceEvent event) {
|
||||
Log.d(TAG, "onEvent(" + event + ")");
|
||||
if (event.action == ServiceEvent.Action.SERVICE_STARTED) {
|
||||
if (controller != null) {
|
||||
controller.init();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by 'handleStatus()' when the PlaybackService is waiting for
|
||||
* a video surface.
|
||||
@ -609,7 +658,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
|
||||
protected abstract void clearStatusMsg();
|
||||
|
||||
protected void onPositionObserverUpdate() {
|
||||
void onPositionObserverUpdate() {
|
||||
if (controller == null || txtvPosition == null || txtvLength == null) {
|
||||
return;
|
||||
}
|
||||
@ -645,12 +694,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
* to the PlaybackService to ensure that the activity has the right
|
||||
* FeedMedia object.
|
||||
*/
|
||||
protected boolean loadMediaInfo() {
|
||||
boolean loadMediaInfo() {
|
||||
Log.d(TAG, "loadMediaInfo()");
|
||||
if(controller == null || controller.getMedia() == null) {
|
||||
return false;
|
||||
}
|
||||
Playable media = controller.getMedia();
|
||||
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
|
||||
showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
|
||||
onPositionObserverUpdate();
|
||||
@ -659,18 +707,18 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updatePlaybackSpeedButton() {
|
||||
void updatePlaybackSpeedButton() {
|
||||
// Only meaningful on AudioplayerActivity, where it is overridden.
|
||||
}
|
||||
|
||||
protected void updatePlaybackSpeedButtonText() {
|
||||
void updatePlaybackSpeedButtonText() {
|
||||
// Only meaningful on AudioplayerActivity, where it is overridden.
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract directions to skip forward or back (rewind) and encapsulates behavior to get or set preference (including update of UI on the skip buttons).
|
||||
*/
|
||||
static public enum SkipDirection {
|
||||
public enum SkipDirection {
|
||||
SKIP_FORWARD(
|
||||
UserPreferences::getFastForwardSecs,
|
||||
MediaplayerActivity::getTxtvFFFromActivity,
|
||||
@ -753,7 +801,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
protected void setupGUI() {
|
||||
void setupGUI() {
|
||||
setContentView(getContentViewResourceId());
|
||||
sbPosition = (SeekBar) findViewById(R.id.sbPosition);
|
||||
txtvPosition = (TextView) findViewById(R.id.txtvPosition);
|
||||
@ -823,11 +871,12 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
}
|
||||
|
||||
if (butSkip != null) {
|
||||
butSkip.setOnClickListener(v -> sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE)));
|
||||
butSkip.setOnClickListener(v ->
|
||||
IntentUtils.sendLocalBroadcast(MediaplayerActivity.this, PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
|
||||
}
|
||||
}
|
||||
|
||||
protected void onRewind() {
|
||||
void onRewind() {
|
||||
if (controller == null) {
|
||||
return;
|
||||
}
|
||||
@ -835,14 +884,15 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
controller.seekTo(curr - UserPreferences.getRewindSecs() * 1000);
|
||||
}
|
||||
|
||||
protected void onPlayPause() {
|
||||
void onPlayPause() {
|
||||
if(controller == null) {
|
||||
return;
|
||||
}
|
||||
controller.init();
|
||||
controller.playPause();
|
||||
}
|
||||
|
||||
protected void onFastForward() {
|
||||
void onFastForward() {
|
||||
if (controller == null) {
|
||||
return;
|
||||
}
|
||||
@ -852,7 +902,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
|
||||
protected abstract int getContentViewResourceId();
|
||||
|
||||
void handleError(int errorCode) {
|
||||
private void handleError(int errorCode) {
|
||||
final AlertDialog.Builder errorDialog = new AlertDialog.Builder(this);
|
||||
errorDialog.setTitle(R.string.error_label);
|
||||
errorDialog.setMessage(MediaPlayerError.getErrorString(this, errorCode));
|
||||
@ -865,7 +915,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
errorDialog.create().show();
|
||||
}
|
||||
|
||||
float prog;
|
||||
private float prog;
|
||||
|
||||
@Override
|
||||
public void onProgressChanged (SeekBar seekBar,int progress, boolean fromUser) {
|
||||
@ -914,4 +964,39 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
||||
}
|
||||
}
|
||||
|
||||
void playExternalMedia(Intent intent, MediaType type) {
|
||||
if (intent == null || intent.getData() == null) {
|
||||
return;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 23
|
||||
&& ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||
Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||
REQUEST_CODE_STORAGE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath());
|
||||
ExternalMedia media = new ExternalMedia(intent.getData().getPath(), type);
|
||||
|
||||
new PlaybackServiceStarter(this, media)
|
||||
.startWhenPrepared(true)
|
||||
.shouldStream(false)
|
||||
.prepareImmediately(true)
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
||||
if (requestCode == REQUEST_CODE_STORAGE) {
|
||||
if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
@ -47,6 +48,7 @@ import de.danoeh.antennapod.core.service.playback.PlayerStatus;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||
import de.danoeh.antennapod.dialog.RenameFeedDialog;
|
||||
@ -60,7 +62,6 @@ import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
|
||||
import de.danoeh.antennapod.fragment.QueueFragment;
|
||||
import de.danoeh.antennapod.fragment.SubscriptionFragment;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
import de.greenrobot.event.EventBus;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
@ -72,16 +73,17 @@ import rx.schedulers.Schedulers;
|
||||
*/
|
||||
public abstract class MediaplayerInfoActivity extends MediaplayerActivity implements NavDrawerActivity {
|
||||
|
||||
private static final String TAG = "MediaplayerInfoActivity";
|
||||
|
||||
private static final int POS_COVER = 0;
|
||||
private static final int POS_DESCR = 1;
|
||||
private static final int POS_CHAPTERS = 2;
|
||||
private static final int NUM_CONTENT_FRAGMENTS = 3;
|
||||
|
||||
final String TAG = "MediaplayerInfoActivity";
|
||||
private static final String PREFS = "AudioPlayerActivityPreferences";
|
||||
private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition";
|
||||
|
||||
public static final String[] NAV_DRAWER_TAGS = {
|
||||
private static final String[] NAV_DRAWER_TAGS = {
|
||||
QueueFragment.TAG,
|
||||
EpisodesFragment.TAG,
|
||||
SubscriptionFragment.TAG,
|
||||
@ -91,8 +93,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
NavListAdapter.SUBSCRIPTION_LIST_TAG
|
||||
};
|
||||
|
||||
protected Button butPlaybackSpeed;
|
||||
protected ImageButton butCastDisconnect;
|
||||
Button butPlaybackSpeed;
|
||||
ImageButton butCastDisconnect;
|
||||
private DrawerLayout drawerLayout;
|
||||
private NavListAdapter navAdapter;
|
||||
private ListView navList;
|
||||
@ -112,6 +114,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
supportPostponeEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
@ -145,7 +153,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
setTheme(UserPreferences.getNoTitleTheme());
|
||||
}
|
||||
|
||||
protected void saveCurrentFragment() {
|
||||
void saveCurrentFragment() {
|
||||
if(pager == null) {
|
||||
return;
|
||||
}
|
||||
@ -153,7 +161,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
|
||||
prefs.edit()
|
||||
.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, pager.getCurrentItem())
|
||||
.commit();
|
||||
.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -235,7 +243,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
|
||||
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close);
|
||||
drawerToggle.setDrawerIndicatorEnabled(false);
|
||||
drawerLayout.setDrawerListener(drawerToggle);
|
||||
drawerLayout.addDrawerListener(drawerToggle);
|
||||
|
||||
navAdapter = new NavListAdapter(itemAccess, this);
|
||||
navList.setAdapter(navAdapter);
|
||||
@ -263,7 +271,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
|
||||
findViewById(R.id.nav_settings).setOnClickListener(v -> {
|
||||
drawerLayout.closeDrawer(navDrawer);
|
||||
startActivity(new Intent(MediaplayerInfoActivity.this, PreferenceController.getPreferenceActivity()));
|
||||
startActivity(new Intent(MediaplayerInfoActivity.this, PreferenceActivity.class));
|
||||
});
|
||||
|
||||
butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
|
||||
@ -277,6 +285,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
pageIndicator.setViewPager(pager);
|
||||
loadLastFragment();
|
||||
pager.onSaveInstanceState();
|
||||
|
||||
navList.post(this::supportStartPostponedEnterTransition);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -297,7 +307,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
return true;
|
||||
}
|
||||
|
||||
public void notifyMediaPositionChanged() {
|
||||
private void notifyMediaPositionChanged() {
|
||||
if(pagerAdapter == null) {
|
||||
return;
|
||||
}
|
||||
@ -387,12 +397,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
new RenameFeedDialog(this, feed).show();
|
||||
return true;
|
||||
case R.id.remove_item:
|
||||
final FeedRemover remover = new FeedRemover(this, feed) {
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
};
|
||||
final FeedRemover remover = new FeedRemover(this, feed);
|
||||
ConfirmationDialog conDialog = new ConfirmationDialog(this,
|
||||
R.string.remove_feed_label,
|
||||
getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
|
||||
@ -404,12 +409,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
Playable playable = controller.getMedia();
|
||||
if (playable != null && playable instanceof FeedMedia) {
|
||||
FeedMedia media = (FeedMedia) playable;
|
||||
if (media.getItem().getFeed().getId() == feed.getId()) {
|
||||
if (media.getItem() != null && media.getItem().getFeed() != null &&
|
||||
media.getItem().getFeed().getId() == feed.getId()) {
|
||||
Log.d(TAG, "Currently playing episode is about to be deleted, skipping");
|
||||
remover.skipOnCompletion = true;
|
||||
if(controller.getStatus() == PlayerStatus.PLAYING) {
|
||||
sendBroadcast(new Intent(
|
||||
PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
|
||||
IntentUtils.sendLocalBroadcast(MediaplayerInfoActivity.this, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -438,7 +443,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
}
|
||||
}
|
||||
|
||||
public void showDrawerPreferencesDialog() {
|
||||
private void showDrawerPreferencesDialog() {
|
||||
final List<String> hiddenDrawerItems = UserPreferences.getHiddenDrawerItems();
|
||||
String[] navLabels = new String[NAV_DRAWER_TAGS.length];
|
||||
final boolean[] checked = new boolean[NAV_DRAWER_TAGS.length];
|
||||
@ -483,14 +488,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
||||
View parentLayout = findViewById(R.id.drawer_layout);
|
||||
Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT);
|
||||
if (event.action != null) {
|
||||
snackbar.setAction(getString(R.string.undo), v -> {
|
||||
event.action.run();
|
||||
});
|
||||
snackbar.setAction(getString(R.string.undo), v -> event.action.run());
|
||||
}
|
||||
snackbar.show();
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
|
@ -5,8 +5,9 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
@ -55,7 +56,6 @@ import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
|
||||
import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult;
|
||||
import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
|
||||
import de.danoeh.antennapod.core.util.DownloadError;
|
||||
import de.danoeh.antennapod.core.util.FileNameGenerator;
|
||||
@ -66,7 +66,6 @@ import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
|
||||
import de.danoeh.antennapod.dialog.AuthenticationDialog;
|
||||
import de.greenrobot.event.EventBus;
|
||||
import rx.Observable;
|
||||
import rx.Subscriber;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
@ -84,7 +83,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
public static final String ARG_FEEDURL = "arg.feedurl";
|
||||
// Optional argument: specify a title for the actionbar.
|
||||
public static final String ARG_TITLE = "title";
|
||||
public static final int RESULT_ERROR = 2;
|
||||
private static final int RESULT_ERROR = 2;
|
||||
private static final String TAG = "OnlineFeedViewActivity";
|
||||
private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE;
|
||||
private volatile List<Feed> feeds;
|
||||
@ -101,7 +100,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
private Subscription download;
|
||||
private Subscription parser;
|
||||
private Subscription updater;
|
||||
private EventDistributor.EventListener listener = new EventDistributor.EventListener() {
|
||||
private final EventDistributor.EventListener listener = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) {
|
||||
@ -112,9 +111,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
feeds -> {
|
||||
OnlineFeedViewActivity.this.feeds = feeds;
|
||||
setSubscribeButtonState(feed);
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
}
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error))
|
||||
);
|
||||
} else if ((arg & EVENTS) != 0) {
|
||||
setSubscribeButtonState(feed);
|
||||
@ -131,10 +128,13 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
if (getIntent() != null && getIntent().hasExtra(ARG_TITLE)) {
|
||||
getSupportActionBar().setTitle(getIntent().getStringExtra(ARG_TITLE));
|
||||
if (actionBar != null && getIntent() != null && getIntent().hasExtra(ARG_TITLE)) {
|
||||
actionBar.setTitle(getIntent().getStringExtra(ARG_TITLE));
|
||||
}
|
||||
|
||||
StorageUtils.checkStorageAvailability(this);
|
||||
@ -146,7 +146,9 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
|| TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
|
||||
feedUrl = (TextUtils.equals(getIntent().getAction(), Intent.ACTION_SEND))
|
||||
? getIntent().getStringExtra(Intent.EXTRA_TEXT) : getIntent().getDataString();
|
||||
getSupportActionBar().setTitle(R.string.add_feed_label);
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(R.string.add_feed_label);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Activity must be started with feedurl argument!");
|
||||
}
|
||||
@ -265,16 +267,11 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password,
|
||||
true, null);
|
||||
|
||||
download = Observable.create(new Observable.OnSubscribe<DownloadStatus>() {
|
||||
@Override
|
||||
public void call(Subscriber<? super DownloadStatus> subscriber) {
|
||||
feeds = DBReader.getFeedList();
|
||||
downloader = new HttpDownloader(request);
|
||||
downloader.call();
|
||||
Log.d(TAG, "Download was completed");
|
||||
subscriber.onNext(downloader.getResult());
|
||||
subscriber.onCompleted();
|
||||
}
|
||||
download = Observable.fromCallable(() -> {
|
||||
feeds = DBReader.getFeedList();
|
||||
downloader = new HttpDownloader(request);
|
||||
downloader.call();
|
||||
return downloader.getResult();
|
||||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -286,6 +283,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
if (status == null) {
|
||||
Log.wtf(TAG, "DownloadStatus returned by Downloader was null");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (status.isCancelled()) {
|
||||
return;
|
||||
@ -300,7 +298,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
}
|
||||
} else {
|
||||
String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this);
|
||||
if (errorMsg != null && status.getReasonDetailed() != null) {
|
||||
if (status.getReasonDetailed() != null) {
|
||||
errorMsg += " (" + status.getReasonDetailed() + ")";
|
||||
}
|
||||
showErrorDialog(errorMsg);
|
||||
@ -313,39 +311,38 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
}
|
||||
Log.d(TAG, "Parsing feed");
|
||||
|
||||
parser = Observable.create(new Observable.OnSubscribe<FeedHandlerResult>() {
|
||||
@Override
|
||||
public void call(Subscriber<? super FeedHandlerResult> subscriber) {
|
||||
FeedHandler handler = new FeedHandler();
|
||||
try {
|
||||
FeedHandlerResult result = handler.parseFeed(feed);
|
||||
subscriber.onNext(result);
|
||||
} catch (UnsupportedFeedtypeException e) {
|
||||
Log.d(TAG, "Unsupported feed type detected");
|
||||
if (TextUtils.equals("html", e.getRootElement().toLowerCase())) {
|
||||
showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url());
|
||||
} else {
|
||||
subscriber.onError(e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
subscriber.onError(e);
|
||||
} finally {
|
||||
boolean rc = new File(feed.getFile_url()).delete();
|
||||
Log.d(TAG, "Deleted feed source file. Result: " + rc);
|
||||
subscriber.onCompleted();
|
||||
parser = Observable.fromCallable(() -> {
|
||||
FeedHandler handler = new FeedHandler();
|
||||
try {
|
||||
return handler.parseFeed(feed);
|
||||
} catch (UnsupportedFeedtypeException e) {
|
||||
Log.d(TAG, "Unsupported feed type detected");
|
||||
if ("html".equalsIgnoreCase(e.getRootElement())) {
|
||||
showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url());
|
||||
return null;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
throw e;
|
||||
} finally {
|
||||
boolean rc = new File(feed.getFile_url()).delete();
|
||||
Log.d(TAG, "Deleted feed source file. Result: " + rc);
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
beforeShowFeedInformation(result.feed);
|
||||
showFeedInformation(result.feed, result.alternateFeedUrls);
|
||||
if(result != null) {
|
||||
beforeShowFeedInformation(result.feed);
|
||||
showFeedInformation(result.feed, result.alternateFeedUrls);
|
||||
}
|
||||
}, error -> {
|
||||
String errorMsg = DownloadError.ERROR_PARSER_EXCEPTION.getErrorString(
|
||||
OnlineFeedViewActivity.this) + " (" + error.getMessage() + ")";
|
||||
showErrorDialog(errorMsg);
|
||||
Log.d(TAG, "Feed parser exception: " + Log.getStackTraceString(error));
|
||||
});
|
||||
}
|
||||
|
||||
@ -383,8 +380,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
this.selectedDownloadUrl = feed.getDownload_url();
|
||||
EventDistributor.getInstance().register(listener);
|
||||
ListView listView = (ListView) findViewById(R.id.listview);
|
||||
LayoutInflater inflater = (LayoutInflater)
|
||||
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
LayoutInflater inflater = LayoutInflater.from(this);
|
||||
View header = inflater.inflate(R.layout.onlinefeedview_header, listView, false);
|
||||
listView.addHeaderView(header);
|
||||
|
||||
@ -398,9 +394,9 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
|
||||
subscribeButton = (Button) header.findViewById(R.id.butSubscribe);
|
||||
|
||||
if (feed.getImage() != null && StringUtils.isNotBlank(feed.getImage().getDownload_url())) {
|
||||
if (StringUtils.isNotBlank(feed.getImageUrl())) {
|
||||
Glide.with(this)
|
||||
.load(feed.getImage().getDownload_url())
|
||||
.load(feed.getImageUrl())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
@ -414,7 +410,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
description.setText(feed.getDescription());
|
||||
|
||||
subscribeButton.setOnClickListener(v -> {
|
||||
if(feed != null && feedInFeedlist(feed)) {
|
||||
if(feedInFeedlist(feed)) {
|
||||
Intent intent = new Intent(OnlineFeedViewActivity.this, MainActivity.class);
|
||||
// feed.getId() is always 0, we have to retrieve the id from the feed list from
|
||||
// the database
|
||||
@ -508,8 +504,8 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void showErrorDialog(String errorMsg) {
|
||||
assert(Looper.myLooper() == Looper.getMainLooper()); // run on UI thread
|
||||
if (!isFinishing() && !isPaused) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.error_label);
|
||||
@ -586,7 +582,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
|
||||
private class FeedViewAuthenticationDialog extends AuthenticationDialog {
|
||||
|
||||
private String feedUrl;
|
||||
private final String feedUrl;
|
||||
|
||||
FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) {
|
||||
super(context, titleRes, true, false, null, null);
|
||||
|
@ -68,7 +68,7 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
protected void importUri(@Nullable Uri uri) {
|
||||
void importUri(@Nullable Uri uri) {
|
||||
if(uri == null) {
|
||||
new MaterialDialog.Builder(this)
|
||||
.content(R.string.opml_import_error_no_file)
|
||||
@ -114,7 +114,7 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
/** Starts the import process. */
|
||||
protected void startImport() {
|
||||
private void startImport() {
|
||||
try {
|
||||
Reader mReader = new InputStreamReader(getContentResolver().openInputStream(uri), LangUtils.UTF_8);
|
||||
importWorker = new OpmlImportWorker(this, mReader) {
|
||||
@ -144,7 +144,7 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean finishWhenCanceled() {
|
||||
boolean finishWhenCanceled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,12 @@
|
||||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
@ -16,6 +14,9 @@ import android.widget.FrameLayout;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import com.bytehamster.lib.preferencesearch.SearchPreference;
|
||||
import com.bytehamster.lib.preferencesearch.SearchPreferenceResult;
|
||||
import com.bytehamster.lib.preferencesearch.SearchPreferenceResultListener;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
@ -24,25 +25,40 @@ import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
* PreferenceActivity for API 11+. In order to change the behavior of the preference UI, see
|
||||
* PreferenceController.
|
||||
*/
|
||||
public class PreferenceActivity extends AppCompatActivity {
|
||||
public class PreferenceActivity extends AppCompatActivity implements SearchPreferenceResultListener {
|
||||
|
||||
public static final String PARAM_RESOURCE = "resource";
|
||||
private static WeakReference<PreferenceActivity> instance;
|
||||
private PreferenceController preferenceController;
|
||||
private MainFragment prefFragment;
|
||||
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
private PreferenceFragmentCompat fragment;
|
||||
|
||||
@Override
|
||||
public Preference findPreference(CharSequence key) {
|
||||
return prefFragment.findPreference(key);
|
||||
public void setFragment(PreferenceFragmentCompat fragment) {
|
||||
this.fragment = fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Activity getActivity() {
|
||||
public PreferenceFragmentCompat getFragment() {
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Preference findPreference(CharSequence key) {
|
||||
return fragment.findPreference(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceScreen getPreferenceScreen() {
|
||||
return fragment.getPreferenceScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppCompatActivity getActivity() {
|
||||
return PreferenceActivity.this;
|
||||
}
|
||||
};
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// This must be the FIRST thing we do, otherwise other code may not have the
|
||||
@ -68,8 +84,21 @@ public class PreferenceActivity extends AppCompatActivity {
|
||||
// since the MainFragment depends on the preferenceController already being created
|
||||
preferenceController = new PreferenceController(preferenceUI);
|
||||
|
||||
prefFragment = new MainFragment();
|
||||
getFragmentManager().beginTransaction().replace(R.id.content, prefFragment).commit();
|
||||
showPreferenceScreen(R.xml.preferences, false);
|
||||
}
|
||||
|
||||
private void showPreferenceScreen(int screen, boolean addHistory) {
|
||||
PreferenceFragmentCompat prefFragment = new MainFragment();
|
||||
preferenceUI.setFragment(prefFragment);
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(PARAM_RESOURCE, screen);
|
||||
prefFragment.setArguments(args);
|
||||
if (addHistory) {
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.content, prefFragment)
|
||||
.addToBackStack(getString(PreferenceController.getTitleOfPage(screen))).commit();
|
||||
} else {
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.content, prefFragment).commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -88,24 +117,40 @@ public class PreferenceActivity extends AppCompatActivity {
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
||||
finish();
|
||||
} else {
|
||||
getSupportFragmentManager().popBackStack();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static class MainFragment extends PreferenceFragment {
|
||||
@Override
|
||||
public void onSearchResultClicked(SearchPreferenceResult result) {
|
||||
showPreferenceScreen(result.getResourceFile(), true);
|
||||
result.highlight(preferenceUI.getFragment());
|
||||
}
|
||||
|
||||
public static class MainFragment extends PreferenceFragmentCompat {
|
||||
private int screen;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
screen = getArguments().getInt(PARAM_RESOURCE);
|
||||
addPreferencesFromResource(screen);
|
||||
PreferenceActivity activity = instance.get();
|
||||
if(activity != null && activity.preferenceController != null) {
|
||||
activity.preferenceController.onCreate();
|
||||
if (activity != null && activity.preferenceController != null) {
|
||||
activity.preferenceUI.setFragment(this);
|
||||
activity.preferenceController.onCreate(screen);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,15 +159,17 @@ public class PreferenceActivity extends AppCompatActivity {
|
||||
super.onResume();
|
||||
PreferenceActivity activity = instance.get();
|
||||
if(activity != null && activity.preferenceController != null) {
|
||||
activity.preferenceController.onResume();
|
||||
activity.setTitle(PreferenceController.getTitleOfPage(screen));
|
||||
activity.preferenceUI.setFragment(this);
|
||||
activity.preferenceController.onResume(screen);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
PreferenceActivity activity = instance.get();
|
||||
if(activity != null && activity.preferenceController != null) {
|
||||
activity.preferenceController.onPause();
|
||||
if (screen == R.xml.preferences_gpodder) {
|
||||
activity.preferenceController.unregisterGpodnet();
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
@ -130,8 +177,8 @@ public class PreferenceActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void onStop() {
|
||||
PreferenceActivity activity = instance.get();
|
||||
if(activity != null && activity.preferenceController != null) {
|
||||
activity.preferenceController.onStop();
|
||||
if (screen == R.xml.preferences_storage) {
|
||||
activity.preferenceController.unsubscribeExportSubscription();
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
@ -1,97 +0,0 @@
|
||||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceScreen;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
|
||||
/**
|
||||
* PreferenceActivity for API 10. In order to change the behavior of the preference UI, see
|
||||
* PreferenceController.
|
||||
*/
|
||||
public class PreferenceActivityGingerbread extends android.preference.PreferenceActivity {
|
||||
private static final String TAG = "PreferenceActivity";
|
||||
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public Preference findPreference(CharSequence key) {
|
||||
return PreferenceActivityGingerbread.this.findPreference(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Activity getActivity() {
|
||||
return PreferenceActivityGingerbread.this;
|
||||
}
|
||||
};
|
||||
private PreferenceController preferenceController;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
preferenceController = new PreferenceController(preferenceUI);
|
||||
preferenceController.onCreate();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
preferenceController.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
preferenceController.onPause();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
preferenceController.onStop();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
|
||||
theme.applyStyle(UserPreferences.getTheme(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
preferenceController.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
|
||||
Preference preference) {
|
||||
super.onPreferenceTreeClick(preferenceScreen, preference);
|
||||
if (preference != null)
|
||||
if (preference instanceof PreferenceScreen)
|
||||
if (((PreferenceScreen) preference).getDialog() != null)
|
||||
((PreferenceScreen) preference)
|
||||
.getDialog()
|
||||
.getWindow()
|
||||
.getDecorView()
|
||||
.setBackgroundDrawable(
|
||||
this.getWindow().getDecorView()
|
||||
.getBackground().getConstantState()
|
||||
.newDrawable()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,23 +1,50 @@
|
||||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.graphics.drawable.DrawableCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.ProgressBar;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
import rx.Completable;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Creator: vbarad
|
||||
* Date: 2016-12-03
|
||||
* Project: AntennaPod
|
||||
* Shows the AntennaPod logo while waiting for the main activity to start
|
||||
*/
|
||||
|
||||
public class SplashActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.splash);
|
||||
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
ProgressBar progressBar = findViewById(R.id.progressBar);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
Drawable wrapDrawable = DrawableCompat.wrap(progressBar.getIndeterminateDrawable());
|
||||
DrawableCompat.setTint(wrapDrawable, 0xffffffff);
|
||||
progressBar.setIndeterminateDrawable(DrawableCompat.unwrap(wrapDrawable));
|
||||
} else {
|
||||
progressBar.getIndeterminateDrawable().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
Completable.create(subscriber -> {
|
||||
// Trigger schema updates
|
||||
PodDBAdapter.getInstance().open();
|
||||
PodDBAdapter.getInstance().close();
|
||||
subscriber.onCompleted();
|
||||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(() -> {
|
||||
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ public class StorageErrorActivity extends AppCompatActivity {
|
||||
startActivity(new Intent(this, MainActivity.class));
|
||||
}
|
||||
|
||||
private BroadcastReceiver mediaUpdate = new BroadcastReceiver() {
|
||||
private final BroadcastReceiver mediaUpdate = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
@ -7,29 +7,34 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.view.WindowCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.SeekBar;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
|
||||
import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import de.danoeh.antennapod.view.AspectRatioVideoView;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
|
||||
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import de.danoeh.antennapod.view.AspectRatioVideoView;
|
||||
|
||||
/**
|
||||
* Activity for playing video files.
|
||||
*/
|
||||
@ -45,12 +50,13 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
|
||||
private VideoControlsHider videoControlsHider = new VideoControlsHider(this);
|
||||
|
||||
private AtomicBoolean isSetup = new AtomicBoolean(false);
|
||||
private final AtomicBoolean isSetup = new AtomicBoolean(false);
|
||||
|
||||
private LinearLayout controls;
|
||||
private LinearLayout videoOverlay;
|
||||
private AspectRatioVideoView videoview;
|
||||
private ProgressBar progressIndicator;
|
||||
private FrameLayout videoframe;
|
||||
|
||||
@Override
|
||||
protected void chooseTheme() {
|
||||
@ -70,20 +76,8 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (getIntent().getAction() != null
|
||||
&& getIntent().getAction().equals(Intent.ACTION_VIEW)) {
|
||||
Intent intent = getIntent();
|
||||
Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath());
|
||||
ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
|
||||
MediaType.VIDEO);
|
||||
Intent launchIntent = new Intent(this, PlaybackService.class);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
|
||||
true);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
|
||||
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
|
||||
true);
|
||||
startService(launchIntent);
|
||||
if (TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
|
||||
playExternalMedia(getIntent(), MediaType.VIDEO);
|
||||
} else if (PlaybackService.isCasting()) {
|
||||
Intent intent = PlaybackService.getPlayerActivityIntent(this);
|
||||
if (!intent.getComponent().getClassName().equals(VideoplayerActivity.class.getName())) {
|
||||
@ -94,11 +88,28 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
|
||||
videoControlsHider.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserLeaveHint () {
|
||||
if (!PictureInPictureUtil.isInPictureInPictureMode(this) && UserPreferences.getVideoBackgroundBehavior()
|
||||
== UserPreferences.VideoBackgroundBehavior.PICTURE_IN_PICTURE) {
|
||||
compatEnterPictureInPicture();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
videoControlsHider.stop();
|
||||
if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
|
||||
controller.pause();
|
||||
if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
|
||||
if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
|
||||
controller.pause();
|
||||
}
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
@ -126,7 +137,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
|
||||
@Override
|
||||
protected void setupGUI() {
|
||||
if(isSetup.getAndSet(true)) {
|
||||
if (isSetup.getAndSet(true)) {
|
||||
return;
|
||||
}
|
||||
super.setupGUI();
|
||||
@ -134,34 +145,30 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
controls = (LinearLayout) findViewById(R.id.controls);
|
||||
videoOverlay = (LinearLayout) findViewById(R.id.overlay);
|
||||
videoview = (AspectRatioVideoView) findViewById(R.id.videoview);
|
||||
videoframe = (FrameLayout) findViewById(R.id.videoframe);
|
||||
progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
|
||||
videoview.getHolder().addCallback(surfaceHolderCallback);
|
||||
videoview.setOnTouchListener(onVideoviewTouched);
|
||||
videoframe.setOnTouchListener(onVideoviewTouched);
|
||||
videoOverlay.setOnTouchListener((view, motionEvent) -> true); // To suppress touches directly below the slider
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 14) {
|
||||
videoOverlay.setFitsSystemWindows(true);
|
||||
}
|
||||
videoOverlay.setFitsSystemWindows(true);
|
||||
|
||||
setupVideoControlsToggler();
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
videoframe.getViewTreeObserver().addOnGlobalLayoutListener(() ->
|
||||
videoview.setAvailableSize(videoframe.getWidth(), videoframe.getHeight()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAwaitingVideoSurface() {
|
||||
setupVideoAspectRatio();
|
||||
if (videoSurfaceCreated && controller != null) {
|
||||
Log.d(TAG, "Videosurface already created, setting videosurface now");
|
||||
|
||||
Pair<Integer, Integer> videoSize = controller.getVideoSize();
|
||||
if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
|
||||
Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
|
||||
videoview.setVideoSize(videoSize.first, videoSize.second);
|
||||
} else {
|
||||
Log.e(TAG, "Could not determine video size");
|
||||
}
|
||||
controller.setVideoSurface(videoview.getHolder());
|
||||
}
|
||||
}
|
||||
@ -180,8 +187,11 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
progressIndicator.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
View.OnTouchListener onVideoviewTouched = (v, event) -> {
|
||||
private final View.OnTouchListener onVideoviewTouched = (v, event) -> {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (PictureInPictureUtil.isInPictureInPictureMode(this)) {
|
||||
return true;
|
||||
}
|
||||
videoControlsHider.stop();
|
||||
toggleVideoControlsVisibility();
|
||||
if (videoControlsShowing) {
|
||||
@ -194,11 +204,23 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
};
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
void setupVideoControlsToggler() {
|
||||
private void setupVideoControlsToggler() {
|
||||
videoControlsHider.stop();
|
||||
videoControlsHider.start();
|
||||
}
|
||||
|
||||
private void setupVideoAspectRatio() {
|
||||
if (videoSurfaceCreated && controller != null) {
|
||||
Pair<Integer, Integer> videoSize = controller.getVideoSize();
|
||||
if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
|
||||
Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
|
||||
videoview.setVideoSize(videoSize.first, videoSize.second);
|
||||
} else {
|
||||
Log.e(TAG, "Could not determine video size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleVideoControlsVisibility() {
|
||||
if (videoControlsShowing) {
|
||||
getSupportActionBar().hide();
|
||||
@ -247,14 +269,16 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
Log.e(TAG, "Couldn't attach surface to mediaplayer - reference to service was null");
|
||||
}
|
||||
}
|
||||
|
||||
setupVideoAspectRatio();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.d(TAG, "Videosurface was destroyed");
|
||||
videoSurfaceCreated = false;
|
||||
if (controller != null && !destroyingDueToReload) {
|
||||
if (controller != null && !destroyingDueToReload
|
||||
&& UserPreferences.getVideoBackgroundBehavior()
|
||||
!= UserPreferences.VideoBackgroundBehavior.CONTINUE_PLAYING) {
|
||||
controller.notifyVideoSurfaceAbandoned();
|
||||
}
|
||||
}
|
||||
@ -263,6 +287,13 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
|
||||
@Override
|
||||
protected void onReloadNotification(int notificationCode) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && PictureInPictureUtil.isInPictureInPictureMode(this)) {
|
||||
if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO
|
||||
|| notificationCode == PlaybackService.EXTRA_CODE_CAST) {
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) {
|
||||
Log.d(TAG, "ReloadNotification received, switching to Audioplayer now");
|
||||
destroyingDueToReload = true;
|
||||
@ -307,28 +338,31 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
videoOverlay.startAnimation(animation);
|
||||
controls.startAnimation(animation);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 14) {
|
||||
videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
}
|
||||
videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private void hideVideoControls() {
|
||||
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out);
|
||||
if (animation != null) {
|
||||
videoOverlay.startAnimation(animation);
|
||||
controls.startAnimation(animation);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 14) {
|
||||
int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0;
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag);
|
||||
videoOverlay.setFitsSystemWindows(true);
|
||||
private void hideVideoControls(boolean showAnimation) {
|
||||
if (showAnimation) {
|
||||
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out);
|
||||
if (animation != null) {
|
||||
videoOverlay.startAnimation(animation);
|
||||
controls.startAnimation(animation);
|
||||
}
|
||||
}
|
||||
int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0;
|
||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag);
|
||||
videoOverlay.setFitsSystemWindows(true);
|
||||
|
||||
videoOverlay.setVisibility(View.GONE);
|
||||
controls.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void hideVideoControls() {
|
||||
hideVideoControls(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getContentViewResourceId() {
|
||||
return R.layout.videoplayer_activity;
|
||||
@ -344,24 +378,53 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
if (PictureInPictureUtil.supportsPictureInPicture(this)) {
|
||||
menu.findItem(R.id.player_go_to_picture_in_picture).setVisible(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.player_go_to_picture_in_picture) {
|
||||
compatEnterPictureInPicture();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void compatEnterPictureInPicture() {
|
||||
if (PictureInPictureUtil.supportsPictureInPicture(this) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
getSupportActionBar().hide();
|
||||
hideVideoControls(false);
|
||||
enterPictureInPictureMode();
|
||||
}
|
||||
}
|
||||
|
||||
private static class VideoControlsHider extends Handler {
|
||||
|
||||
private static final int DELAY = 2500;
|
||||
|
||||
private WeakReference<VideoplayerActivity> activity;
|
||||
|
||||
public VideoControlsHider(VideoplayerActivity activity) {
|
||||
VideoControlsHider(VideoplayerActivity activity) {
|
||||
this.activity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
private final Runnable hideVideoControls = () -> {
|
||||
VideoplayerActivity vpa = activity.get();
|
||||
if(vpa == null) {
|
||||
VideoplayerActivity vpa = activity != null ? activity.get() : null;
|
||||
if (vpa == null) {
|
||||
return;
|
||||
}
|
||||
if (vpa.videoControlsShowing) {
|
||||
Log.d(TAG, "Hiding video controls");
|
||||
vpa.getSupportActionBar().hide();
|
||||
ActionBar actionBar = vpa.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
vpa.hideVideoControls();
|
||||
vpa.videoControlsShowing = false;
|
||||
}
|
||||
@ -371,7 +434,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
this.postDelayed(hideVideoControls, DELAY);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
void stop() {
|
||||
this.removeCallbacks(hideVideoControls);
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity {
|
||||
private volatile String password;
|
||||
private volatile GpodnetDevice selectedDevice;
|
||||
|
||||
View[] views;
|
||||
private View[] views;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -171,11 +171,7 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
|
||||
authTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, service);
|
||||
} else {
|
||||
authTask.execute();
|
||||
}
|
||||
authTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, service);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package de.danoeh.antennapod.adapter;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
|
||||
public interface ActionButtonCallback {
|
||||
interface ActionButtonCallback {
|
||||
/** Is called when the action button of a list item has been pressed. */
|
||||
void onActionButtonPressed(FeedItem item, LongList queueIds);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
* Utility methods for the action button that is displayed on the right hand side
|
||||
* of a listitem.
|
||||
*/
|
||||
public class ActionButtonUtils {
|
||||
class ActionButtonUtils {
|
||||
|
||||
private final int[] labels;
|
||||
private final TypedArray drawables;
|
||||
|
@ -21,7 +21,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import com.nineoldandroids.view.ViewHelper;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
@ -30,12 +29,12 @@ import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.Converter;
|
||||
import de.danoeh.antennapod.core.util.DateUtils;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
import de.danoeh.antennapod.core.util.NetworkUtils;
|
||||
import de.danoeh.antennapod.core.util.ThemeUtils;
|
||||
import de.danoeh.antennapod.fragment.ItemFragment;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
|
||||
@ -68,11 +67,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
this.actionButtonCallback = actionButtonCallback;
|
||||
this.showOnlyNewEpisodes = showOnlyNewEpisodes;
|
||||
|
||||
if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
|
||||
playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_dark);
|
||||
} else {
|
||||
playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_light);
|
||||
}
|
||||
playingBackGroundColor = ThemeUtils.getColorFromAttr(mainActivity, R.attr.currently_playing_background);
|
||||
normalBackGroundColor = ContextCompat.getColor(mainActivity, android.R.color.transparent);
|
||||
}
|
||||
|
||||
@ -101,7 +96,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
holder.txtvDuration = (TextView) view.findViewById(R.id.txtvDuration);
|
||||
holder.item = null;
|
||||
holder.mainActivityRef = mainActivityRef;
|
||||
holder.position = -1;
|
||||
// so we can grab this later
|
||||
view.setTag(holder);
|
||||
|
||||
@ -113,11 +107,10 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
final FeedItem item = itemAccess.getItem(position);
|
||||
if (item == null) return;
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
this.position = position;
|
||||
this.position = holder.getAdapterPosition();
|
||||
return false;
|
||||
});
|
||||
holder.item = item;
|
||||
holder.position = position;
|
||||
holder.placeholder.setVisibility(View.VISIBLE);
|
||||
holder.placeholder.setText(item.getFeed().getTitle());
|
||||
holder.title.setText(item.getTitle());
|
||||
@ -129,9 +122,9 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
holder.statusUnread.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if(item.isPlayed()) {
|
||||
ViewHelper.setAlpha(holder.content, 0.5f);
|
||||
holder.content.setAlpha(0.5f);
|
||||
} else {
|
||||
ViewHelper.setAlpha(holder.content, 1.0f);
|
||||
holder.content.setAlpha(1.0f);
|
||||
}
|
||||
|
||||
FeedMedia media = item.getMedia();
|
||||
@ -174,7 +167,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
holder.progress.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
holder.progress.setVisibility(View.GONE);
|
||||
holder.progress.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if(media.isCurrentlyPlaying()) {
|
||||
@ -183,7 +176,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
holder.container.setBackgroundColor(normalBackGroundColor);
|
||||
}
|
||||
} else {
|
||||
holder.progress.setVisibility(View.GONE);
|
||||
holder.progress.setVisibility(View.INVISIBLE);
|
||||
holder.txtvDuration.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@ -228,7 +221,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
return pos;
|
||||
}
|
||||
|
||||
private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
|
||||
private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
FeedItem item = (FeedItem) v.getTag();
|
||||
@ -253,7 +246,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
ImageButton butSecondary;
|
||||
FeedItem item;
|
||||
WeakReference<MainActivity> mainActivityRef;
|
||||
int position;
|
||||
|
||||
public Holder(View itemView) {
|
||||
super(itemView);
|
||||
@ -266,18 +258,18 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
MainActivity mainActivity = mainActivityRef.get();
|
||||
if (mainActivity != null) {
|
||||
long[] ids = itemAccess.getItemsIds().toArray();
|
||||
mainActivity.loadChildFragment(ItemFragment.newInstance(ids, position));
|
||||
mainActivity.loadChildFragment(ItemFragment.newInstance(ids, getAdapterPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemSelected() {
|
||||
ViewHelper.setAlpha(itemView, 0.5f);
|
||||
itemView.setAlpha(0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClear() {
|
||||
ViewHelper.setAlpha(itemView, 1.0f);
|
||||
itemView.setAlpha(1.0f);
|
||||
}
|
||||
|
||||
public FeedItem getFeedItem() { return item; }
|
||||
@ -303,6 +295,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
||||
}
|
||||
};
|
||||
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
|
||||
|
||||
contextMenuInterface.setItemVisibility(R.id.mark_as_seen_item, item.isNew());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.util.Linkify;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
@ -20,9 +19,9 @@ import android.widget.TextView;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.util.ChapterUtils;
|
||||
import de.danoeh.antennapod.core.util.Converter;
|
||||
import de.danoeh.antennapod.core.util.ThemeUtils;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
|
||||
public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
|
||||
@ -144,9 +143,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
|
||||
|
||||
Chapter current = ChapterUtils.getCurrentChapter(media);
|
||||
if (current == sc) {
|
||||
boolean darkTheme = UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark;
|
||||
int highlight = darkTheme ? R.color.highlight_dark : R.color.highlight_light;
|
||||
int playingBackGroundColor = ContextCompat.getColor(getContext(), highlight);
|
||||
int playingBackGroundColor = ThemeUtils.getColorFromAttr(getContext(), R.attr.currently_playing_background);
|
||||
holder.view.setBackgroundColor(playingBackGroundColor);
|
||||
} else {
|
||||
holder.view.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
|
||||
|
@ -1,7 +1,6 @@
|
||||
package de.danoeh.antennapod.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
@ -6,6 +6,8 @@ import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
@ -80,13 +82,19 @@ public class DefaultActionButtonCallback implements ActionButtonCallback {
|
||||
Toast.makeText(context, R.string.download_canceled_msg, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else { // media is downloaded
|
||||
if (item.hasMedia() && item.getMedia().isCurrentlyPlaying()) {
|
||||
context.sendBroadcast(new Intent(PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
|
||||
}
|
||||
else if (item.hasMedia() && item.getMedia().isCurrentlyPaused()) {
|
||||
context.sendBroadcast(new Intent(PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE));
|
||||
}
|
||||
else {
|
||||
if (media.isCurrentlyPlaying()) {
|
||||
new PlaybackServiceStarter(context, media)
|
||||
.startWhenPrepared(true)
|
||||
.shouldStream(false)
|
||||
.start();
|
||||
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
|
||||
} else if (media.isCurrentlyPaused()) {
|
||||
new PlaybackServiceStarter(context, media)
|
||||
.startWhenPrepared(true)
|
||||
.shouldStream(false)
|
||||
.start();
|
||||
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE);
|
||||
} else {
|
||||
DBTasks.playMedia(context, media, false, true, false);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import com.joanzapata.iconify.widget.IconTextView;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadStatus;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
@ -29,11 +28,11 @@ import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
/** Displays a list of DownloadStatus entries. */
|
||||
public class DownloadLogAdapter extends BaseAdapter {
|
||||
|
||||
private final String TAG = "DownloadLogAdapter";
|
||||
private static final String TAG = "DownloadLogAdapter";
|
||||
|
||||
private Context context;
|
||||
private final Context context;
|
||||
|
||||
private ItemAccess itemAccess;
|
||||
private final ItemAccess itemAccess;
|
||||
|
||||
public DownloadLogAdapter(Context context, ItemAccess itemAccess) {
|
||||
super();
|
||||
@ -67,8 +66,6 @@ public class DownloadLogAdapter extends BaseAdapter {
|
||||
holder.type.setText(R.string.download_type_feed);
|
||||
} else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
|
||||
holder.type.setText(R.string.download_type_media);
|
||||
} else if (status.getFeedfileType() == FeedImage.FEEDFILETYPE_FEEDIMAGE) {
|
||||
holder.type.setText(R.string.download_type_image);
|
||||
}
|
||||
if (status.getTitle() != null) {
|
||||
holder.title.setText(status.getTitle());
|
||||
@ -94,8 +91,7 @@ public class DownloadLogAdapter extends BaseAdapter {
|
||||
}
|
||||
holder.reason.setText(reasonText);
|
||||
holder.reason.setVisibility(View.VISIBLE);
|
||||
if(status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE &&
|
||||
!newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) {
|
||||
if(!newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) {
|
||||
holder.retry.setVisibility(View.VISIBLE);
|
||||
holder.retry.setOnClickListener(clickListener);
|
||||
ButtonHolder btnHolder;
|
||||
|
@ -12,11 +12,11 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.nineoldandroids.view.ViewHelper;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.util.Converter;
|
||||
import de.danoeh.antennapod.core.util.DateUtils;
|
||||
|
||||
@ -87,9 +87,9 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
|
||||
.into(holder.imageView);
|
||||
|
||||
if(item.isPlayed()) {
|
||||
ViewHelper.setAlpha(convertView, 0.5f);
|
||||
convertView.setAlpha(0.5f);
|
||||
} else {
|
||||
ViewHelper.setAlpha(convertView, 1.0f);
|
||||
convertView.setAlpha(1.0f);
|
||||
}
|
||||
|
||||
holder.title.setText(item.getTitle());
|
||||
@ -99,10 +99,12 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
|
||||
holder.pubDate.setText(pubDateStr);
|
||||
|
||||
FeedItem.State state = item.getState();
|
||||
if (state == FeedItem.State.PLAYING) {
|
||||
if (state == FeedItem.State.PLAYING && PlaybackService.isRunning) {
|
||||
holder.butSecondary.setEnabled(false);
|
||||
holder.butSecondary.setAlpha(0.5f);
|
||||
} else {
|
||||
holder.butSecondary.setEnabled(true);
|
||||
holder.butSecondary.setAlpha(1.0f);
|
||||
}
|
||||
holder.butSecondary.setFocusable(false);
|
||||
holder.butSecondary.setTag(item);
|
||||
@ -111,7 +113,7 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
|
||||
private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
FeedItem item = (FeedItem) v.getTag();
|
||||
|
@ -19,11 +19,11 @@ import de.danoeh.antennapod.core.util.ThemeUtils;
|
||||
|
||||
public class DownloadlistAdapter extends BaseAdapter {
|
||||
|
||||
public static final int SELECTION_NONE = -1;
|
||||
private static final int SELECTION_NONE = -1;
|
||||
|
||||
private int selectedItemIndex;
|
||||
private ItemAccess itemAccess;
|
||||
private Context context;
|
||||
private final ItemAccess itemAccess;
|
||||
private final Context context;
|
||||
|
||||
public DownloadlistAdapter(Context context,
|
||||
ItemAccess itemAccess) {
|
||||
@ -105,7 +105,7 @@ public class DownloadlistAdapter extends BaseAdapter {
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private View.OnClickListener butSecondaryListener = new View.OnClickListener() {
|
||||
private final View.OnClickListener butSecondaryListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Downloader downloader = (Downloader) v.getTag();
|
||||
@ -121,15 +121,6 @@ public class DownloadlistAdapter extends BaseAdapter {
|
||||
ImageButton butSecondary;
|
||||
}
|
||||
|
||||
public int getSelectedItemIndex() {
|
||||
return selectedItemIndex;
|
||||
}
|
||||
|
||||
public void setSelectedItemIndex(int selectedItemIndex) {
|
||||
this.selectedItemIndex = selectedItemIndex;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public interface ItemAccess {
|
||||
int getCount();
|
||||
|
||||
|
@ -17,13 +17,10 @@ import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nineoldandroids.view.ViewHelper;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.DateUtils;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
@ -34,16 +31,16 @@ import de.danoeh.antennapod.core.util.ThemeUtils;
|
||||
*/
|
||||
public class FeedItemlistAdapter extends BaseAdapter {
|
||||
|
||||
private ActionButtonCallback callback;
|
||||
private final ActionButtonCallback callback;
|
||||
private final ItemAccess itemAccess;
|
||||
private final Context context;
|
||||
private boolean showFeedtitle;
|
||||
private int selectedItemIndex;
|
||||
private final boolean showFeedtitle;
|
||||
private final int selectedItemIndex;
|
||||
/** true if played items should be made partially transparent */
|
||||
private boolean makePlayedItemsTransparent;
|
||||
private final boolean makePlayedItemsTransparent;
|
||||
private final ActionButtonUtils actionButtonUtils;
|
||||
|
||||
public static final int SELECTION_NONE = -1;
|
||||
private static final int SELECTION_NONE = -1;
|
||||
|
||||
private final int playingBackGroundColor;
|
||||
private final int normalBackGroundColor;
|
||||
@ -62,11 +59,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
||||
this.actionButtonUtils = new ActionButtonUtils(context);
|
||||
this.makePlayedItemsTransparent = makePlayedItemsTransparent;
|
||||
|
||||
if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
|
||||
playingBackGroundColor = ContextCompat.getColor(context, R.color.highlight_dark);
|
||||
} else {
|
||||
playingBackGroundColor = ContextCompat.getColor(context, R.color.highlight_light);
|
||||
}
|
||||
playingBackGroundColor = ThemeUtils.getColorFromAttr(context, R.attr.currently_playing_background);
|
||||
normalBackGroundColor = ContextCompat.getColor(context, android.R.color.transparent);
|
||||
}
|
||||
|
||||
@ -145,9 +138,9 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
||||
holder.statusUnread.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if(item.isPlayed() && makePlayedItemsTransparent) {
|
||||
ViewHelper.setAlpha(convertView, 0.5f);
|
||||
convertView.setAlpha(0.5f);
|
||||
} else {
|
||||
ViewHelper.setAlpha(convertView, 1.0f);
|
||||
convertView.setAlpha(1.0f);
|
||||
}
|
||||
|
||||
String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
|
||||
@ -157,7 +150,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
||||
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media == null) {
|
||||
holder.episodeProgress.setVisibility(View.GONE);
|
||||
holder.episodeProgress.setVisibility(View.INVISIBLE);
|
||||
holder.inPlaylist.setVisibility(View.INVISIBLE);
|
||||
holder.type.setVisibility(View.INVISIBLE);
|
||||
holder.lenSize.setVisibility(View.INVISIBLE);
|
||||
@ -176,7 +169,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
||||
holder.episodeProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
|
||||
} else {
|
||||
if(media.getPosition() == 0) {
|
||||
holder.episodeProgress.setVisibility(View.GONE);
|
||||
holder.episodeProgress.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,10 @@ import de.danoeh.antennapod.fragment.SubscriptionFragment;
|
||||
public class NavListAdapter extends BaseAdapter
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
public static final int VIEW_TYPE_COUNT = 3;
|
||||
private static final int VIEW_TYPE_COUNT = 3;
|
||||
public static final int VIEW_TYPE_NAV = 0;
|
||||
public static final int VIEW_TYPE_SECTION_DIVIDER = 1;
|
||||
public static final int VIEW_TYPE_SUBSCRIPTION = 2;
|
||||
private static final int VIEW_TYPE_SUBSCRIPTION = 2;
|
||||
|
||||
/**
|
||||
* a tag used as a placeholder to indicate if the subscription list should be displayed or not
|
||||
@ -62,8 +62,8 @@ public class NavListAdapter extends BaseAdapter
|
||||
private static List<String> tags;
|
||||
private static String[] titles;
|
||||
|
||||
private ItemAccess itemAccess;
|
||||
private WeakReference<Activity> activity;
|
||||
private final ItemAccess itemAccess;
|
||||
private final WeakReference<Activity> activity;
|
||||
private boolean showSubscriptionList = true;
|
||||
|
||||
public NavListAdapter(ItemAccess itemAccess, Activity context) {
|
||||
@ -86,9 +86,7 @@ public class NavListAdapter extends BaseAdapter
|
||||
private void loadItems() {
|
||||
List<String> newTags = new ArrayList<>(Arrays.asList(MainActivity.NAV_DRAWER_TAGS));
|
||||
List<String> hiddenFragments = UserPreferences.getHiddenDrawerItems();
|
||||
for(String hidden : hiddenFragments) {
|
||||
newTags.remove(hidden);
|
||||
}
|
||||
newTags.removeAll(hiddenFragments);
|
||||
|
||||
if (newTags.contains(SUBSCRIPTION_LIST_TAG)) {
|
||||
// we never want SUBSCRIPTION_LIST_TAG to be in 'tags'
|
||||
|
@ -24,8 +24,8 @@ import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import com.nineoldandroids.view.ViewHelper;
|
||||
|
||||
import de.danoeh.antennapod.core.util.ThemeUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@ -51,7 +51,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
||||
|
||||
private static final String TAG = QueueRecyclerAdapter.class.getSimpleName();
|
||||
|
||||
private WeakReference<MainActivity> mainActivity;
|
||||
private final WeakReference<MainActivity> mainActivity;
|
||||
private final ItemAccess itemAccess;
|
||||
private final ActionButtonCallback actionButtonCallback;
|
||||
private final ActionButtonUtils actionButtonUtils;
|
||||
@ -76,11 +76,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
||||
this.itemTouchHelper = itemTouchHelper;
|
||||
locked = UserPreferences.isQueueLocked();
|
||||
|
||||
if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
|
||||
playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_dark);
|
||||
} else {
|
||||
playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_light);
|
||||
}
|
||||
playingBackGroundColor = ThemeUtils.getColorFromAttr(mainActivity, R.attr.currently_playing_background);
|
||||
normalBackGroundColor = ContextCompat.getColor(mainActivity, android.R.color.transparent);
|
||||
}
|
||||
|
||||
@ -198,12 +194,12 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
||||
|
||||
@Override
|
||||
public void onItemSelected() {
|
||||
ViewHelper.setAlpha(itemView, 0.5f);
|
||||
itemView.setAlpha(0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClear() {
|
||||
ViewHelper.setAlpha(itemView, 1.0f);
|
||||
itemView.setAlpha(1.0f);
|
||||
}
|
||||
|
||||
public void bind(FeedItem item) {
|
||||
@ -280,7 +276,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
||||
progressLeft.setText("");
|
||||
}
|
||||
progressRight.setText(Converter.getDurationStringLong(media.getDuration()));
|
||||
progressBar.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if(media.isCurrentlyPlaying()) {
|
||||
@ -305,7 +301,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
||||
|
||||
}
|
||||
|
||||
private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
|
||||
private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
FeedItem item = (FeedItem) v.getTag();
|
||||
|
@ -11,7 +11,6 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.nineoldandroids.view.ViewHelper;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
@ -97,7 +96,7 @@ public class SearchlistAdapter extends BaseAdapter {
|
||||
holder.subtitle.setText(result.getSubtitle());
|
||||
}
|
||||
|
||||
ViewHelper.setAlpha(convertView, item.isPlayed() ? 0.5f : 1.0f);
|
||||
convertView.setAlpha(item.isPlayed() ? 0.5f : 1.0f);
|
||||
|
||||
Glide.with(context)
|
||||
.load(item.getFeed().getImageLocation())
|
||||
|
@ -23,8 +23,8 @@ import de.danoeh.antennapod.core.util.Converter;
|
||||
* Adapter for the statistics list
|
||||
*/
|
||||
public class StatisticsListAdapter extends BaseAdapter {
|
||||
private Context context;
|
||||
List<DBReader.StatisticsItem> feedTime = new ArrayList<>();
|
||||
private final Context context;
|
||||
private List<DBReader.StatisticsItem> feedTime = new ArrayList<>();
|
||||
private boolean countAll = true;
|
||||
|
||||
public StatisticsListAdapter(Context context) {
|
||||
|
@ -50,7 +50,6 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
|
||||
}
|
||||
|
||||
private int getAdjustedPosition(int origPosition) {
|
||||
assert(origPosition != getAddTilePosition());
|
||||
return origPosition < getAddTilePosition() ? origPosition : origPosition - 1;
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
||||
* @param json object holding the podcast information
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static Podcast fromSearch(JSONObject json) throws JSONException {
|
||||
public static Podcast fromSearch(JSONObject json) {
|
||||
String title = json.optString("collectionName", "");
|
||||
String imageUrl = json.optString("artworkUrl100", null);
|
||||
String feedUrl = json.optString("feedUrl", null);
|
||||
@ -162,7 +162,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
||||
/**
|
||||
* View holder object for the GridView
|
||||
*/
|
||||
class PodcastViewHolder {
|
||||
static class PodcastViewHolder {
|
||||
|
||||
/**
|
||||
* ImageView holding the Podcast image
|
||||
|
@ -23,15 +23,15 @@ public class ExportWorker {
|
||||
private static final String TAG = "ExportWorker";
|
||||
private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds";
|
||||
|
||||
private ExportWriter exportWriter;
|
||||
private File output;
|
||||
private final ExportWriter exportWriter;
|
||||
private final File output;
|
||||
|
||||
public ExportWorker(ExportWriter exportWriter) {
|
||||
this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR),
|
||||
DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension()));
|
||||
}
|
||||
|
||||
public ExportWorker(ExportWriter exportWriter, @NonNull File output) {
|
||||
private ExportWorker(ExportWriter exportWriter, @NonNull File output) {
|
||||
this.exportWriter = exportWriter;
|
||||
this.output = output;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package de.danoeh.antennapod.asynctask;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
@ -16,9 +15,9 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
|
||||
/** Queues items for download in the background. */
|
||||
public class OpmlFeedQueuer extends AsyncTask<Void, Void, Void> {
|
||||
private Context context;
|
||||
private final Context context;
|
||||
private ProgressDialog progDialog;
|
||||
private int[] selection;
|
||||
private final int[] selection;
|
||||
|
||||
public OpmlFeedQueuer(Context context, int[] selection) {
|
||||
super();
|
||||
@ -56,13 +55,8 @@ public class OpmlFeedQueuer extends AsyncTask<Void, Void, Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public void executeAsync() {
|
||||
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
|
||||
executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||
} else {
|
||||
execute();
|
||||
}
|
||||
executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package de.danoeh.antennapod.asynctask;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
@ -21,12 +20,12 @@ public class OpmlImportWorker extends
|
||||
AsyncTask<Void, Void, ArrayList<OpmlElement>> {
|
||||
private static final String TAG = "OpmlImportWorker";
|
||||
|
||||
private Context context;
|
||||
private final Context context;
|
||||
private Exception exception;
|
||||
|
||||
private ProgressDialog progDialog;
|
||||
|
||||
private Reader mReader;
|
||||
private final Reader mReader;
|
||||
|
||||
public OpmlImportWorker(Context context, Reader reader) {
|
||||
super();
|
||||
@ -93,13 +92,8 @@ public class OpmlImportWorker extends
|
||||
return exception != null;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public void executeAsync() {
|
||||
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
|
||||
executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||
} else {
|
||||
execute();
|
||||
}
|
||||
executeOnExecutor(THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import de.danoeh.antennapod.core.ClientConfig;
|
||||
/**
|
||||
* Configures the ClientConfig class of the core package.
|
||||
*/
|
||||
public class ClientConfigurator {
|
||||
class ClientConfigurator {
|
||||
|
||||
private ClientConfigurator(){}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package de.danoeh.antennapod.config;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.os.Build;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.AudioplayerActivity;
|
||||
import de.danoeh.antennapod.activity.CastplayerActivity;
|
||||
@ -18,7 +19,11 @@ public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks {
|
||||
return new Intent(context, CastplayerActivity.class);
|
||||
}
|
||||
if (mediaType == MediaType.VIDEO) {
|
||||
return new Intent(context, VideoplayerActivity.class);
|
||||
Intent i = new Intent(context, VideoplayerActivity.class);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||
}
|
||||
return i;
|
||||
} else {
|
||||
return new Intent(context, AudioplayerActivity.class);
|
||||
}
|
||||
|
@ -32,14 +32,14 @@ import de.danoeh.antennapod.core.util.LongList;
|
||||
|
||||
public class EpisodesApplyActionFragment extends Fragment {
|
||||
|
||||
public String TAG = "EpisodeActionFragment";
|
||||
public static final String TAG = "EpisodeActionFragment";
|
||||
|
||||
public static final int ACTION_QUEUE = 1;
|
||||
public static final int ACTION_MARK_PLAYED = 2;
|
||||
public static final int ACTION_MARK_UNPLAYED = 4;
|
||||
public static final int ACTION_DOWNLOAD = 8;
|
||||
private static final int ACTION_MARK_PLAYED = 2;
|
||||
private static final int ACTION_MARK_UNPLAYED = 4;
|
||||
private static final int ACTION_DOWNLOAD = 8;
|
||||
public static final int ACTION_REMOVE = 16;
|
||||
public static final int ACTION_ALL = ACTION_QUEUE | ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED
|
||||
private static final int ACTION_ALL = ACTION_QUEUE | ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED
|
||||
| ACTION_DOWNLOAD | ACTION_REMOVE;
|
||||
|
||||
private ListView mListView;
|
||||
|
@ -8,6 +8,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.gpoddernet.GpodnetService;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
|
@ -43,7 +43,7 @@ public class ProxyDialog {
|
||||
|
||||
private static final String TAG = "ProxyDialog";
|
||||
|
||||
private Context context;
|
||||
private final Context context;
|
||||
|
||||
private MaterialDialog dialog;
|
||||
|
||||
@ -243,47 +243,44 @@ public class ProxyDialog {
|
||||
txtvMessage.setTextColor(textColorPrimary);
|
||||
txtvMessage.setText("{fa-circle-o-notch spin} " + checking);
|
||||
txtvMessage.setVisibility(View.VISIBLE);
|
||||
subscription = Observable.create(new Observable.OnSubscribe<Response>() {
|
||||
@Override
|
||||
public void call(Subscriber<? super Response> subscriber) {
|
||||
String type = (String) spType.getSelectedItem();
|
||||
String host = etHost.getText().toString();
|
||||
String port = etPort.getText().toString();
|
||||
String username = etUsername.getText().toString();
|
||||
String password = etPassword.getText().toString();
|
||||
int portValue = 8080;
|
||||
if(!TextUtils.isEmpty(port)) {
|
||||
portValue = Integer.valueOf(port);
|
||||
}
|
||||
SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
|
||||
Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
|
||||
Proxy proxy = new Proxy(proxyType, address);
|
||||
OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder()
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.proxy(proxy);
|
||||
builder.interceptors().clear();
|
||||
OkHttpClient client = builder.build();
|
||||
if(!TextUtils.isEmpty(username)) {
|
||||
String credentials = Credentials.basic(username, password);
|
||||
client.interceptors().add(chain -> {
|
||||
Request request = chain.request().newBuilder()
|
||||
.header("Proxy-Authorization", credentials).build();
|
||||
return chain.proceed(request);
|
||||
});
|
||||
}
|
||||
Request request = new Request.Builder()
|
||||
.url("http://www.google.com")
|
||||
.head()
|
||||
.build();
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
subscriber.onNext(response);
|
||||
} catch(IOException e) {
|
||||
subscriber.onError(e);
|
||||
}
|
||||
subscriber.onCompleted();
|
||||
}
|
||||
})
|
||||
subscription = Observable.create((Observable.OnSubscribe<Response>) subscriber -> {
|
||||
String type = (String) spType.getSelectedItem();
|
||||
String host = etHost.getText().toString();
|
||||
String port = etPort.getText().toString();
|
||||
String username = etUsername.getText().toString();
|
||||
String password = etPassword.getText().toString();
|
||||
int portValue = 8080;
|
||||
if(!TextUtils.isEmpty(port)) {
|
||||
portValue = Integer.valueOf(port);
|
||||
}
|
||||
SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
|
||||
Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
|
||||
Proxy proxy = new Proxy(proxyType, address);
|
||||
OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder()
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.proxy(proxy);
|
||||
builder.interceptors().clear();
|
||||
OkHttpClient client = builder.build();
|
||||
if(!TextUtils.isEmpty(username)) {
|
||||
String credentials = Credentials.basic(username, password);
|
||||
client.interceptors().add(chain -> {
|
||||
Request request = chain.request().newBuilder()
|
||||
.header("Proxy-Authorization", credentials).build();
|
||||
return chain.proceed(request);
|
||||
});
|
||||
}
|
||||
Request request = new Request.Builder()
|
||||
.url("http://www.google.com")
|
||||
.head()
|
||||
.build();
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
subscriber.onNext(response);
|
||||
} catch(IOException e) {
|
||||
subscriber.onError(e);
|
||||
}
|
||||
subscriber.onCompleted();
|
||||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
|
@ -56,7 +56,7 @@ public class RatingDialog {
|
||||
}
|
||||
}
|
||||
|
||||
public static void rateNow() {
|
||||
private static void rateNow() {
|
||||
Context context = mContext.get();
|
||||
if(context == null) {
|
||||
return;
|
||||
@ -69,11 +69,11 @@ public class RatingDialog {
|
||||
saveRated();
|
||||
}
|
||||
|
||||
public static boolean rated() {
|
||||
private static boolean rated() {
|
||||
return mPreferences.getBoolean(KEY_RATED, false);
|
||||
}
|
||||
|
||||
public static void saveRated() {
|
||||
private static void saveRated() {
|
||||
mPreferences
|
||||
.edit()
|
||||
.putBoolean(KEY_RATED, true)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package de.danoeh.antennapod.dialog;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
@ -9,7 +8,6 @@ import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
@ -26,7 +24,7 @@ public abstract class SleepTimerDialog {
|
||||
|
||||
private static final String TAG = SleepTimerDialog.class.getSimpleName();
|
||||
|
||||
private Context context;
|
||||
private final Context context;
|
||||
|
||||
private MaterialDialog dialog;
|
||||
private EditText etxtTime;
|
||||
|
@ -52,7 +52,7 @@ public class VariableSpeedDialog {
|
||||
builder.neutralText(R.string.close_label);
|
||||
builder.onPositive((dialog, which) -> {
|
||||
if (Build.VERSION.SDK_INT >= 16) { // just to be safe
|
||||
UserPreferences.enableSonic(true);
|
||||
UserPreferences.enableSonic();
|
||||
if(showSpeedSelector) {
|
||||
showSpeedSelectorDialog(context);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public class AddFeedFragment extends Fragment {
|
||||
/**
|
||||
* Preset value for url text field.
|
||||
*/
|
||||
public static final String ARG_FEED_URL = "feedurl";
|
||||
private static final String ARG_FEED_URL = "feedurl";
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
@ -66,4 +66,15 @@ public class AddFeedFragment extends Fragment {
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
|
||||
// So, we certainly *don't* have an options menu,
|
||||
// but unless we say we do, old options menus sometimes
|
||||
// persist. mfietz thinks this causes the ActionBar to be invalidated
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
@ -36,12 +38,12 @@ import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
@ -69,24 +71,24 @@ public class AllEpisodesFragment extends Fragment {
|
||||
private static final String PREF_SCROLL_POSITION = "scroll_position";
|
||||
private static final String PREF_SCROLL_OFFSET = "scroll_offset";
|
||||
|
||||
protected RecyclerView recyclerView;
|
||||
protected AllEpisodesRecycleAdapter listAdapter;
|
||||
RecyclerView recyclerView;
|
||||
AllEpisodesRecycleAdapter listAdapter;
|
||||
private ProgressBar progLoading;
|
||||
|
||||
protected List<FeedItem> episodes;
|
||||
List<FeedItem> episodes;
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
private boolean itemsLoaded = false;
|
||||
private boolean viewsCreated = false;
|
||||
|
||||
private boolean isUpdatingFeeds;
|
||||
protected boolean isMenuInvalidationAllowed = false;
|
||||
boolean isMenuInvalidationAllowed = false;
|
||||
|
||||
protected Subscription subscription;
|
||||
Subscription subscription;
|
||||
private LinearLayoutManager layoutManager;
|
||||
|
||||
protected boolean showOnlyNewEpisodes() { return false; }
|
||||
protected String getPrefName() { return DEFAULT_PREF_NAME; }
|
||||
boolean showOnlyNewEpisodes() { return false; }
|
||||
String getPrefName() { return DEFAULT_PREF_NAME; }
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@ -165,7 +167,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
protected void resetViewState() {
|
||||
void resetViewState() {
|
||||
viewsCreated = false;
|
||||
listAdapter = null;
|
||||
}
|
||||
@ -284,13 +286,17 @@ public class AllEpisodesFragment extends Fragment {
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
try {
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
// Mark as seen contains UI logic specific to All/New/FavoriteSegments,
|
||||
// e.g., Undo with Snackbar,
|
||||
// and is handled by this class rather than the generic FeedItemMenuHandler
|
||||
// Undo is useful for Mark as seen, given there is no UI to undo it otherwise,
|
||||
// i.e., there is context menu item for Mark as new
|
||||
if (R.id.mark_as_seen_item == item.getItemId()) {
|
||||
markItemAsSeenWithUndo(selectedItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -299,10 +305,10 @@ public class AllEpisodesFragment extends Fragment {
|
||||
R.layout.all_episodes_fragment);
|
||||
}
|
||||
|
||||
protected View onCreateViewHelper(LayoutInflater inflater,
|
||||
ViewGroup container,
|
||||
Bundle savedInstanceState,
|
||||
int fragmentResource) {
|
||||
View onCreateViewHelper(LayoutInflater inflater,
|
||||
ViewGroup container,
|
||||
Bundle savedInstanceState,
|
||||
int fragmentResource) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
View root = inflater.inflate(fragmentResource, container, false);
|
||||
@ -346,7 +352,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||
updateShowOnlyEpisodesListViewState();
|
||||
}
|
||||
|
||||
protected AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
|
||||
private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
@ -444,7 +450,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EVENTS) != 0) {
|
||||
@ -459,7 +465,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||
private void updateShowOnlyEpisodesListViewState() {
|
||||
}
|
||||
|
||||
protected void loadItems() {
|
||||
void loadItems() {
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
@ -483,8 +489,40 @@ public class AllEpisodesFragment extends Fragment {
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
protected List<FeedItem> loadData() {
|
||||
List<FeedItem> loadData() {
|
||||
return DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT);
|
||||
}
|
||||
|
||||
void markItemAsSeenWithUndo(FeedItem item) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "markItemAsSeenWithUndo(" + item.getId() + ")");
|
||||
if (subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
// we're marking it as unplayed since the user didn't actually play it
|
||||
// but they don't want it considered 'NEW' anymore
|
||||
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
|
||||
|
||||
final Handler h = new Handler(getActivity().getMainLooper());
|
||||
final Runnable r = () -> {
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
|
||||
DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
|
||||
}
|
||||
};
|
||||
|
||||
Snackbar snackbar = Snackbar.make(getView(), getString(R.string.marked_as_seen_label),
|
||||
Snackbar.LENGTH_LONG);
|
||||
snackbar.setAction(getString(R.string.undo), v -> {
|
||||
DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
|
||||
// don't forget to cancel the thing that's going to remove the media
|
||||
h.removeCallbacks(r);
|
||||
});
|
||||
snackbar.show();
|
||||
h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -140,18 +140,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
if(items != null) {
|
||||
inflater.inflate(R.menu.downloads_completed, menu);
|
||||
MenuItem episodeActions = menu.findItem(R.id.episode_actions);
|
||||
if(items.size() > 0) {
|
||||
int[] attrs = {R.attr.action_bar_icon_color};
|
||||
TypedArray ta = getActivity().obtainStyledAttributes(UserPreferences.getTheme(), attrs);
|
||||
int textColor = ta.getColor(0, Color.GRAY);
|
||||
ta.recycle();
|
||||
episodeActions.setIcon(new IconDrawable(getActivity(),
|
||||
FontAwesomeIcons.fa_gears).color(textColor).actionBarSize());
|
||||
episodeActions.setVisible(true);
|
||||
} else {
|
||||
episodeActions.setVisible(false);
|
||||
}
|
||||
menu.findItem(R.id.episode_actions).setVisible(items.size() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +149,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.episode_actions:
|
||||
EpisodesApplyActionFragment fragment = EpisodesApplyActionFragment
|
||||
.newInstance(items, EpisodesApplyActionFragment.ACTION_REMOVE);
|
||||
.newInstance(items, EpisodesApplyActionFragment.ACTION_REMOVE | EpisodesApplyActionFragment.ACTION_QUEUE);
|
||||
((MainActivity) getActivity()).loadChildFragment(fragment);
|
||||
return true;
|
||||
default:
|
||||
@ -168,7 +157,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
|
||||
private final DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
|
||||
@Override
|
||||
public int getCount() {
|
||||
return (items != null) ? items.size() : 0;
|
||||
@ -189,7 +178,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
}
|
||||
};
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EVENTS) != 0) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ListFragment;
|
||||
@ -13,9 +15,11 @@ import android.widget.ListView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.widget.TextView;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.adapter.DownloadLogAdapter;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadStatus;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
@ -82,7 +86,30 @@ public class DownloadLogFragment extends ListFragment {
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private DownloadLogAdapter.ItemAccess itemAccess = new DownloadLogAdapter.ItemAccess() {
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
|
||||
DownloadStatus status = adapter.getItem(position);
|
||||
String url = "unknown";
|
||||
String message = getString(R.string.download_successful);
|
||||
FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId());
|
||||
if (media != null) {
|
||||
url = media.getDownload_url();
|
||||
}
|
||||
if (!status.isSuccessful()) {
|
||||
message = status.getReasonDetailed();
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setTitle(R.string.download_error_details);
|
||||
builder.setMessage(getString(R.string.download_error_details_message, message, url));
|
||||
builder.setPositiveButton(android.R.string.ok, null);
|
||||
Dialog dialog = builder.show();
|
||||
((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true);
|
||||
}
|
||||
|
||||
private final DownloadLogAdapter.ItemAccess itemAccess = new DownloadLogAdapter.ItemAccess() {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
@ -99,7 +126,7 @@ public class DownloadLogFragment extends ListFragment {
|
||||
}
|
||||
};
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
|
@ -25,7 +25,7 @@ public class DownloadsFragment extends Fragment {
|
||||
public static final String ARG_SELECTED_TAB = "selected_tab";
|
||||
|
||||
public static final int POS_RUNNING = 0;
|
||||
public static final int POS_COMPLETED = 1;
|
||||
private static final int POS_COMPLETED = 1;
|
||||
public static final int POS_LOG = 2;
|
||||
|
||||
private static final String PREF_LAST_TAB_POSITION = "tab_position";
|
||||
@ -78,9 +78,9 @@ public class DownloadsFragment extends Fragment {
|
||||
viewPager.setCurrentItem(lastPosition);
|
||||
}
|
||||
|
||||
public class DownloadsPagerAdapter extends FragmentPagerAdapter {
|
||||
public static class DownloadsPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
Resources resources;
|
||||
final Resources resources;
|
||||
|
||||
public DownloadsPagerAdapter(FragmentManager fm, Resources resources) {
|
||||
super(fm);
|
||||
|
@ -21,10 +21,10 @@ public class EpisodesFragment extends Fragment {
|
||||
public static final String TAG = "EpisodesFragment";
|
||||
private static final String PREF_LAST_TAB_POSITION = "tab_position";
|
||||
|
||||
public static final int POS_NEW_EPISODES = 0;
|
||||
public static final int POS_ALL_EPISODES = 1;
|
||||
public static final int POS_FAV_EPISODES = 2;
|
||||
public static final int TOTAL_COUNT = 3;
|
||||
private static final int POS_NEW_EPISODES = 0;
|
||||
private static final int POS_ALL_EPISODES = 1;
|
||||
private static final int POS_FAV_EPISODES = 2;
|
||||
private static final int TOTAL_COUNT = 3;
|
||||
|
||||
|
||||
private TabLayout tabLayout;
|
||||
@ -79,7 +79,7 @@ public class EpisodesFragment extends Fragment {
|
||||
public static class EpisodesPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private final Resources resources;
|
||||
private AllEpisodesFragment[] fragments = {
|
||||
private final AllEpisodesFragment[] fragments = {
|
||||
new NewEpisodesFragment(),
|
||||
new AllEpisodesFragment(),
|
||||
new FavoriteEpisodesFragment()
|
||||
@ -106,7 +106,7 @@ public class EpisodesFragment extends Fragment {
|
||||
case POS_ALL_EPISODES:
|
||||
return resources.getString(R.string.all_episodes_short_label);
|
||||
case POS_NEW_EPISODES:
|
||||
return resources.getString(R.string.new_label);
|
||||
return resources.getString(R.string.new_episodes_label);
|
||||
case POS_FAV_EPISODES:
|
||||
return resources.getString(R.string.favorite_episodes_label);
|
||||
default:
|
||||
|
@ -1,6 +1,9 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@ -14,11 +17,15 @@ import android.widget.TextView;
|
||||
import com.bumptech.glide.Glide;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.util.Converter;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||
import rx.Single;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Fragment which is supposed to be displayed outside of the MediaplayerActivity
|
||||
@ -33,8 +40,8 @@ public class ExternalPlayerFragment extends Fragment {
|
||||
private ImageButton butPlay;
|
||||
private TextView mFeedName;
|
||||
private ProgressBar mProgressBar;
|
||||
|
||||
private PlaybackController controller;
|
||||
private Subscription subscription;
|
||||
|
||||
public ExternalPlayerFragment() {
|
||||
super();
|
||||
@ -56,8 +63,15 @@ public class ExternalPlayerFragment extends Fragment {
|
||||
Log.d(TAG, "layoutInfo was clicked");
|
||||
|
||||
if (controller != null && controller.getMedia() != null) {
|
||||
startActivity(PlaybackService.getPlayerActivityIntent(
|
||||
getActivity(), controller.getMedia()));
|
||||
Intent intent = PlaybackService.getPlayerActivityIntent(getActivity(), controller.getMedia());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16 && controller.getMedia().getMediaType() == MediaType.AUDIO) {
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat.
|
||||
makeSceneTransitionAnimation(getActivity(), imgvCover, "coverTransition");
|
||||
startActivity(intent, options.toBundle());
|
||||
} else {
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
return root;
|
||||
@ -68,10 +82,15 @@ public class ExternalPlayerFragment extends Fragment {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
controller = setupPlaybackController();
|
||||
butPlay.setOnClickListener(v -> {
|
||||
if(controller != null) {
|
||||
if (controller != null) {
|
||||
controller.playPause();
|
||||
}
|
||||
});
|
||||
loadMediaInfo();
|
||||
}
|
||||
|
||||
public void connectToPlaybackService() {
|
||||
controller.init();
|
||||
}
|
||||
|
||||
private PlaybackController setupPlaybackController() {
|
||||
@ -112,9 +131,9 @@ public class ExternalPlayerFragment extends Fragment {
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
onPositionObserverUpdate();
|
||||
|
||||
controller.init();
|
||||
mProgressBar.setProgress((int)
|
||||
((double) controller.getPosition() / controller.getDuration() * 100));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -124,6 +143,9 @@ public class ExternalPlayerFragment extends Fragment {
|
||||
if (controller != null) {
|
||||
controller.release();
|
||||
}
|
||||
if (subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -144,7 +166,7 @@ public class ExternalPlayerFragment extends Fragment {
|
||||
controller = setupPlaybackController();
|
||||
if (butPlay != null) {
|
||||
butPlay.setOnClickListener(v -> {
|
||||
if(controller != null) {
|
||||
if (controller != null) {
|
||||
controller.playPause();
|
||||
}
|
||||
});
|
||||
@ -154,50 +176,56 @@ public class ExternalPlayerFragment extends Fragment {
|
||||
|
||||
private boolean loadMediaInfo() {
|
||||
Log.d(TAG, "Loading media info");
|
||||
if (controller != null && controller.serviceAvailable()) {
|
||||
Playable media = controller.getMedia();
|
||||
if (media != null) {
|
||||
txtvTitle.setText(media.getEpisodeTitle());
|
||||
mFeedName.setText(media.getFeedTitle());
|
||||
mProgressBar.setProgress((int)
|
||||
((double) controller.getPosition() / controller.getDuration() * 100));
|
||||
|
||||
Glide.with(getActivity())
|
||||
.load(media.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(imgvCover);
|
||||
|
||||
fragmentLayout.setVisibility(View.VISIBLE);
|
||||
if (controller.isPlayingVideoLocally()) {
|
||||
butPlay.setVisibility(View.GONE);
|
||||
} else {
|
||||
butPlay.setVisibility(View.VISIBLE);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
Log.w(TAG, "loadMediaInfo was called while the media object of playbackService was null!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "loadMediaInfo was called while playbackService was null!");
|
||||
if (controller == null) {
|
||||
Log.w(TAG, "loadMediaInfo was called while PlaybackController was null!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
subscription = Single.create(subscriber -> subscriber.onSuccess(controller.getMedia()))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(media -> updateUi((Playable) media));
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getPositionString(int position, int duration) {
|
||||
return Converter.getDurationStringLong(position) + " / "
|
||||
+ Converter.getDurationStringLong(duration);
|
||||
private void updateUi(Playable media) {
|
||||
if (media != null) {
|
||||
txtvTitle.setText(media.getEpisodeTitle());
|
||||
mFeedName.setText(media.getFeedTitle());
|
||||
onPositionObserverUpdate();
|
||||
|
||||
Glide.with(getActivity())
|
||||
.load(media.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(imgvCover);
|
||||
|
||||
fragmentLayout.setVisibility(View.VISIBLE);
|
||||
if (controller.isPlayingVideoLocally()) {
|
||||
butPlay.setVisibility(View.GONE);
|
||||
} else {
|
||||
butPlay.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "loadMediaInfo was called while the media object of playbackService was null!");
|
||||
}
|
||||
}
|
||||
|
||||
public PlaybackController getPlaybackControllerTestingOnly() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
public void onPositionObserverUpdate() {
|
||||
private void onPositionObserverUpdate() {
|
||||
if (controller.getPosition() == PlaybackService.INVALID_TIME
|
||||
|| controller.getDuration() == PlaybackService.INVALID_TIME) {
|
||||
return;
|
||||
}
|
||||
mProgressBar.setProgress((int)
|
||||
((double) controller.getPosition() / controller.getDuration() * 100));
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
|
||||
public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
||||
|
||||
public static final String TAG = "FavoriteEpisodesFrag";
|
||||
private static final String TAG = "FavoriteEpisodesFrag";
|
||||
|
||||
private static final String PREF_NAME = "PrefFavoriteEpisodesFragment";
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class FyydSearchFragment extends Fragment {
|
||||
private Button butRetry;
|
||||
private TextView txtvEmpty;
|
||||
|
||||
private FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient());
|
||||
private final FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient());
|
||||
|
||||
/**
|
||||
* List of podcasts retreived from the search
|
||||
@ -169,7 +169,7 @@ public class FyydSearchFragment extends Fragment {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
void processSearchResult(FyydResponse response) {
|
||||
private void processSearchResult(FyydResponse response) {
|
||||
adapter.clear();
|
||||
if (!response.getData().isEmpty()) {
|
||||
adapter.clear();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user