Merge branch 'develop'
This commit is contained in:
commit
e884e989c7
|
@ -42,3 +42,4 @@ libs
|
|||
src/de/danoeh/antennapod/util/flattr/FlattrConfig.java
|
||||
gradle.properties
|
||||
*.keystore
|
||||
*.p12
|
||||
|
|
29
.tx/config
29
.tx/config
|
@ -4,6 +4,7 @@ host = https://www.transifex.com
|
|||
[antennapod.english]
|
||||
source_file = core/src/main/res/values/strings.xml
|
||||
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.ca = core/src/main/res/values-ca/strings.xml
|
||||
|
@ -14,18 +15,23 @@ trans.de = core/src/main/res/values-de/strings.xml
|
|||
trans.el = core/src/main/res/values-el/strings.xml
|
||||
trans.es = core/src/main/res/values-es/strings.xml
|
||||
trans.es_ES = core/src/main/res/values-es-rES/strings.xml
|
||||
trans.et = core/src/main/res/values-et/strings.xml
|
||||
trans.fa = core/src/main/res/values-fa/strings.xml
|
||||
trans.fi = core/src/main/res/values-fi/strings.xml
|
||||
trans.fr = core/src/main/res/values-fr/strings.xml
|
||||
trans.gl = core/src/main/res/values-gl-rES/strings.xml
|
||||
trans.he_IL = core/src/main/res/values-iw-rIL/strings.xml
|
||||
trans.hi_IN = core/src/main/res/values-hi-rIN/strings.xml
|
||||
trans.hu = core/src/main/res/values-hu/strings.xml
|
||||
trans.id = core/src/main/res/values-id/strings.xml
|
||||
trans.it = core/src/main/res/values-it/strings.xml
|
||||
trans.it_IT = core/src/main/res/values-it-rIT/strings.xml
|
||||
trans.is = core/src/main/res/values-is-rIS/strings.xml
|
||||
trans.ja = core/src/main/res/values-ja/strings.xml
|
||||
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.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
|
||||
|
@ -38,20 +44,29 @@ trans.ro_RO = core/src/main/res/values-ro-rRO/strings.xml
|
|||
trans.ru = core/src/main/res/values-ru/strings.xml
|
||||
trans.ru-RU = core/src/main/res/values-ru/strings.xml
|
||||
trans.ru_RU = core/src/main/res/values-ru/strings.xml
|
||||
trans.uk_UA = core/src/main/res/values-uk-rUA/strings.xml
|
||||
trans.zh_CN = core/src/main/res/values-zh-rCN/strings.xml
|
||||
trans.sv_SE = core/src/main/res/values-sv-rSE/strings.xml
|
||||
trans.sw_KE = core/src/main/res/values-sw-rKE/strings.xml
|
||||
trans.te = core/src/main/res/values-te/strings.xml
|
||||
trans.tr = core/src/main/res/values-tr/strings.xml
|
||||
trans.uk_UA = core/src/main/res/values-uk-rUA/strings.xml
|
||||
trans.vi = core/src/main/res/values-vi/strings.xml
|
||||
trans.vi_VN = core/src/main/res/values-vi-rVN/strings.xml
|
||||
trans_zh = core/src/main/res/values-zh/strings.xml
|
||||
trans.zh_CN = core/src/main/res/values-zh-rCN/strings.xml
|
||||
trans.zh_TW = core/src/main/res/values-zh-rTW/strings.xml
|
||||
trans.zh_HK = core/src/main/res/values-zh-rHK/strings.xml
|
||||
|
||||
[antennapod.description]
|
||||
file_filter = description/<lang>.txt
|
||||
source_file = description/en.txt
|
||||
file_filter = app/src/main/play/<lang>/listing/fulldescription
|
||||
source_file = app/src/main/play/en-US/listing/fulldescription
|
||||
source_lang = en
|
||||
|
||||
[antennapod.shortdescription]
|
||||
file_filter = app/src/main/play/<lang>/listing/shortdescription
|
||||
source_file = app/src/main/play/en-US/listing/shortdescription
|
||||
source_lang = en
|
||||
|
||||
[antennapod.changelog]
|
||||
file_filter = changelog/<lang>.md
|
||||
source_file = CHANGELOG.md
|
||||
file_filter = app/src/main/play/<lang>/whatsnew
|
||||
source_file = app/src/main/play/en-US/whatsnew
|
||||
source_lang = en
|
||||
|
||||
|
|
62
CHANGELOG.md
62
CHANGELOG.md
|
@ -1,20 +1,62 @@
|
|||
Change Log
|
||||
==========
|
||||
|
||||
Version 1.6.3
|
||||
-------------
|
||||
|
||||
* New features:
|
||||
* Support for Android Auto
|
||||
* Sort feeds by number of played episodes
|
||||
* Statistics modes
|
||||
* Setting: Enqueue downloaded
|
||||
* Launch screen
|
||||
* Improvements
|
||||
* Chapter duration
|
||||
* Feed title in deletion confirmation
|
||||
* Fixes:
|
||||
* Episodes refresh spinner
|
||||
* Publication date parsing
|
||||
* Unknown mime type
|
||||
|
||||
Version 1.6.2
|
||||
-------------
|
||||
|
||||
* New features:
|
||||
* Integration of fyyd Podcast Search Engine
|
||||
* Export subscriptions as HTML
|
||||
* Rename feeds
|
||||
* Auto-enable sleep timer
|
||||
* "has media" filter
|
||||
* Force gpodder full sync
|
||||
* Improvements:
|
||||
* Better support for Atom feeds, e.g. summary tag
|
||||
* Confirmation dialog on mark all as seen
|
||||
* Number of downloaded episodes in subscription counter
|
||||
* Gpodder sync error optional
|
||||
* Search results
|
||||
* MRSS support
|
||||
* Sanitize HTML from Atom feed
|
||||
* Fixes:
|
||||
* Reset sleep timer on shake to current waiting time
|
||||
* Cast dialog image
|
||||
* Mini player not showing up
|
||||
* Audio player cover fragment
|
||||
* Prevent out of memory and casting crashes
|
||||
|
||||
Version 1.6.0
|
||||
-------------
|
||||
* New features:
|
||||
* Experimental Chromecast support
|
||||
* Subscription overview
|
||||
* Proxy support
|
||||
* Statistics
|
||||
* Manual gpodder.net sync
|
||||
* Experimental Chromecast support
|
||||
* Subscription overview
|
||||
* Proxy support
|
||||
* Statistics
|
||||
* Manual gpodder.net sync
|
||||
* Fixes:
|
||||
* Audioplayer controls
|
||||
* Audio ducking
|
||||
* Video control fade-out
|
||||
* External media controls
|
||||
* Feed parsing
|
||||
* Audioplayer controls
|
||||
* Audio ducking
|
||||
* Video control fade-out
|
||||
* External media controls
|
||||
* Feed parsing
|
||||
|
||||
Version 1.5.0
|
||||
-------------
|
||||
|
|
|
@ -7,11 +7,11 @@ In particular, please not only tell us that you want something (*what*), but als
|
|||
|
||||
---
|
||||
|
||||
**App version:** 1.x (from Google Play/F-Store/Custom build)
|
||||
**App version:** 1.x (from Google Play/F-Droid/Custom build)
|
||||
|
||||
**Android version**: 5.x [Please mention if you are using a custom rom!]
|
||||
|
||||
**Devide model**:
|
||||
**Device model**:
|
||||
|
||||
**Expected behaviour**:
|
||||
|
||||
|
|
10
README.md
10
README.md
|
@ -2,8 +2,12 @@
|
|||
|
||||
This is the official repository of AntennaPod, the easy-to-use, flexible and open-source podcast manager for Android.
|
||||
|
||||
[![Download from Google Play](http://www.android.com/images/brand/android_app_on_play_large.png "Download from Google Play")](https://play.google.com/store/apps/details?id=de.danoeh.antennapod)
|
||||
[![AntennaPod on fdroid.org](https://camo.githubusercontent.com/7df0eafa4433fa4919a56f87c3d99cf81b68d01c/68747470733a2f2f662d64726f69642e6f72672f77696b692f696d616765732f632f63342f462d44726f69642d627574746f6e5f617661696c61626c652d6f6e2e706e67 "Download from fdroid.org")](https://f-droid.org/repository/browse/?fdid=de.danoeh.antennapod)
|
||||
[<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"
|
||||
alt="Get it on F-Droid"
|
||||
height="90">](https://f-droid.org/app/de.danoeh.antennapod)
|
||||
|
||||
## Feedback
|
||||
You can use the [AntennaPod Google Group](https://groups.google.com/forum/#!forum/antennapod) for discussions about the app.
|
||||
|
@ -17,7 +21,7 @@ AntennaPod has many users and we don't want them to run into trouble when we add
|
|||
|
||||
There are APKs available for every branch that is actively worked on. Please note that these might be very unstable versions of the app, which can break your current installation. Install them at your own risk!
|
||||
|
||||
Click [here](https://www.dropbox.com/sh/4h2kfa2d2jesnu8/AABF7u5QsOn8Lg8MDie4Z4Ama?dl=0) to get to the nightly builds folder.
|
||||
Click [here](https://www.dropbox.com/sh/lzfd640z63qz3fr/AACyxTF1ygR9wMlPLPwVGIUKa?dl=0) to get to the nightly builds folder.
|
||||
|
||||
## License
|
||||
|
||||
|
|
125
app/build.gradle
125
app/build.gradle
|
@ -2,50 +2,13 @@ import org.apache.tools.ant.filters.ReplaceTokens
|
|||
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "me.tatarka.retrolambda"
|
||||
apply plugin: 'com.github.triplet.play'
|
||||
|
||||
repositories {
|
||||
maven { url "https://jitpack.io" }
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(":core")
|
||||
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") {
|
||||
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.okhttp:okhttp:$okhttpVersion"
|
||||
compile "com.squareup.okhttp:okhttp-urlconnection:$okhttpVersion"
|
||||
compile "com.squareup.okio:okio:$okioVersion"
|
||||
compile "de.greenrobot:eventbus:$eventbusVersion"
|
||||
compile "io.reactivex:rxandroid:$rxAndroidVersion"
|
||||
compile "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.github.afollestad.material-dialogs:commons:$materialDialogsVersion") {
|
||||
transitive = true
|
||||
}
|
||||
compile "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion"
|
||||
compile("com.githang:viewpagerindicator:2.5@aar") {
|
||||
exclude module: "support-v4"
|
||||
}
|
||||
|
||||
compile "com.github.shts:TriangleLabelView:$triangleLabelViewVersion"
|
||||
|
||||
compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
|
||||
}
|
||||
|
||||
def getMyVersionName() {
|
||||
def parsedManifestXml = (new XmlSlurper())
|
||||
.parse("${projectDir}/src/main/AndroidManifest.xml")
|
||||
|
@ -67,6 +30,7 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
multiDexEnabled true
|
||||
versionCode getMyVersionCode()
|
||||
versionName "${getMyVersionName()}"
|
||||
testApplicationId "de.test.antennapod"
|
||||
|
@ -137,6 +101,78 @@ android {
|
|||
aaptOptions {
|
||||
additionalParameters "--no-version-vectors"
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
free {
|
||||
}
|
||||
play {
|
||||
}
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
jumboMode true
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
freeDebugCompile
|
||||
freeReleaseCompile
|
||||
playDebugCompile
|
||||
playReleaseCompile
|
||||
}
|
||||
|
||||
dependencies {
|
||||
freeDebugCompile project(path: ":core", configuration: "freeDebug")
|
||||
freeReleaseCompile project(path: ":core", configuration: "freeRelease")
|
||||
// free build hack: skip some dependencies
|
||||
if (!doFreeBuild()) {
|
||||
playDebugCompile project(path: ":core", configuration: "playDebug")
|
||||
playReleaseCompile project(path: ":core", configuration: "playRelease")
|
||||
} else {
|
||||
System.out.println("app: free build hack, skipping some dependencies")
|
||||
}
|
||||
compile 'com.android.support:multidex:1.0.1'
|
||||
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") {
|
||||
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"
|
||||
// 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") {
|
||||
transitive = true
|
||||
}
|
||||
compile "com.yqritc:recyclerview-flexibledivider:$recyclerviewFlexibledividerVersion"
|
||||
compile("com.githang:viewpagerindicator:2.5@aar") {
|
||||
exclude module: "support-v4"
|
||||
}
|
||||
|
||||
compile "com.github.shts:TriangleLabelView:$triangleLabelViewVersion"
|
||||
|
||||
compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
|
||||
|
||||
compile 'com.github.mfietz:fyydlin:v0.1'
|
||||
}
|
||||
|
||||
play {
|
||||
serviceAccountEmail = '522080222319-compute@developer.gserviceaccount.com'
|
||||
pk12File = file('../serviceaccount-c3d7d0f61387.p12')
|
||||
}
|
||||
|
||||
// about.html is templatized so that we can automatically insert
|
||||
|
@ -145,12 +181,13 @@ task filterAbout {
|
|||
inputs.files files(["src/main/templates/about.html",
|
||||
"src/main/AndroidManifest.xml"])
|
||||
outputs.file "src/main/assets/about.html"
|
||||
} << {
|
||||
} doLast {
|
||||
copy {
|
||||
from "src/main/templates/about.html"
|
||||
into "src/main/assets"
|
||||
filter(ReplaceTokens, tokens: [versionname: android.defaultConfig.versionName,
|
||||
commit : "git rev-parse --short HEAD".execute().text])
|
||||
commit : "git rev-parse --short HEAD".execute().text,
|
||||
year : new Date().format('yyyy')])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,3 +201,11 @@ task copyTextFiles(type: Copy) {
|
|||
}
|
||||
|
||||
preBuild.dependsOn filterAbout, copyTextFiles
|
||||
|
||||
allprojects {
|
||||
gradle.projectsEvaluated {
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-Xlint" << "-Xlint:-deprecation" << "-Xlint:-serial"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
public *;
|
||||
}
|
||||
|
||||
-dontwarn com.squareup.okhttp.**
|
||||
-dontwarn okhttp3.**
|
||||
-dontwarn okio.**
|
||||
|
||||
# for RxJava:
|
||||
|
@ -66,8 +66,10 @@
|
|||
-keep interface android.support.v4.** { *; }
|
||||
-keep class !android.support.v7.internal.view.menu.**,android.support.v7.** {*;}
|
||||
-keep interface android.support.v7.** { *; }
|
||||
-keep class com.google.android.wearable.** { *; }
|
||||
-dontwarn android.support.v4.**
|
||||
-dontwarn android.support.v7.**
|
||||
-dontwarn com.google.android.wearable.**
|
||||
|
||||
-keepattributes *Annotation*
|
||||
|
||||
|
@ -107,4 +109,19 @@
|
|||
-dontwarn com.viewpagerindicator.LinePageIndicator
|
||||
|
||||
# for some reason ProGuard removes this file. Why? Unsure.
|
||||
-keep class de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider { *; }
|
||||
-keep class de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider { *; }
|
||||
|
||||
# Retrofit 2.0
|
||||
-dontwarn retrofit2.**
|
||||
-keep class retrofit2.** { *; }
|
||||
-keepattributes Signature
|
||||
-keepattributes Exceptions
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
@retrofit2.http.* <methods>;
|
||||
}
|
||||
|
||||
# Moshi
|
||||
-keep class com.squareup.moshi.** { *; }
|
||||
-keep interface com.squareup.moshi.** { *; }
|
||||
-keep public class retrofit2.adapter.rxjava.RxJavaCallAdapterFactory { *; }
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package de.test.antennapod.service.playback;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
@ -20,6 +22,7 @@ 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.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.PlayerStatus;
|
||||
|
@ -112,7 +115,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
|
||||
public void testInit() {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, defaultCallback);
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, new DefaultPSMPCallback());
|
||||
psmp.shutdown();
|
||||
}
|
||||
|
||||
|
@ -138,7 +141,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectStreamNoStartNoPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(2);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -159,47 +162,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
|
||||
|
@ -217,7 +179,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectStreamStartNoPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(2);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -238,46 +200,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
|
||||
|
@ -296,7 +218,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectStreamNoStartPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(4);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -320,46 +242,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
|
||||
|
@ -376,7 +258,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectStreamStartPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(5);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -403,47 +285,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
|
||||
|
@ -459,7 +300,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectLocalNoStartNoPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(2);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -480,47 +321,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
|
||||
|
@ -537,7 +337,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectLocalStartNoPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(2);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -558,46 +358,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
|
||||
|
@ -614,7 +374,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectLocalNoStartPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(4);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -638,46 +398,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
|
||||
|
@ -693,7 +413,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
public void testPlayMediaObjectLocalStartPrepare() throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(5);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
try {
|
||||
|
@ -721,46 +441,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
countDownLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
|
||||
|
@ -773,58 +453,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
psmp.shutdown();
|
||||
}
|
||||
|
||||
|
||||
private final PlaybackServiceMediaPlayer.PSMPCallback defaultCallback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
checkPSMPInfo(newInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) { return false; }
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
private void pauseTestSkeleton(final PlayerStatus initialState, final boolean stream, final boolean abandonAudioFocus, final boolean reinit, long timeoutSeconds) throws InterruptedException {
|
||||
final Context c = getInstrumentation().getTargetContext();
|
||||
final int latchCount = (stream && reinit) ? 2 : 1;
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
|
||||
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
checkPSMPInfo(newInfo);
|
||||
|
@ -863,42 +497,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = new AssertionFailedError("Unexpected call to shouldStop");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
if (assertionError == null)
|
||||
assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
|
||||
|
@ -955,7 +559,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
(initialState == PlayerStatus.PREPARED) ? 1 : 0;
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
|
||||
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
checkPSMPInfo(newInfo);
|
||||
|
@ -973,36 +577,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
if (assertionError == null) {
|
||||
|
@ -1010,11 +584,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
if (initialState == PlayerStatus.PREPARED || initialState == PlayerStatus.PLAYING || initialState == PlayerStatus.PAUSED) {
|
||||
|
@ -1048,7 +617,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
final Context c = getInstrumentation().getTargetContext();
|
||||
final int latchCount = 1;
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
checkPSMPInfo(newInfo);
|
||||
|
@ -1062,37 +631,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
countDownLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1101,11 +639,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
|
||||
|
@ -1153,7 +686,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
final Context c = getInstrumentation().getTargetContext();
|
||||
final int latchCount = 2;
|
||||
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
|
||||
PlaybackServiceMediaPlayer.PSMPCallback callback = new DefaultPSMPCallback() {
|
||||
@Override
|
||||
public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
|
||||
checkPSMPInfo(newInfo);
|
||||
|
@ -1169,47 +702,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
if (assertionError == null)
|
||||
assertionError = new AssertionFailedError("Unexpected call to onMediaPlayerError");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
|
||||
|
@ -1248,4 +746,71 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
|||
super("Unexpected state change: " + status);
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultPSMPCallback implements PlaybackServiceMediaPlayer.PSMPCallback {
|
||||
@Override
|
||||
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shouldStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeedChanged(float s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpeedAbilityChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(int percent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaChanged(boolean reloadUI) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerInfo(int code, @StringRes int resourceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostPlayback(@NonNull Playable media, boolean ended, boolean skipped, boolean playingNext) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackStart(@NonNull Playable playable, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackPause(Playable playable, int position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Playable getNextInQueue(Playable currentMedia) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,58 +218,43 @@ public class DBReaderTest extends InstrumentationTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private List<FeedItem> saveUnreadItems(int numItems) {
|
||||
if (numItems <= 0) {
|
||||
throw new IllegalArgumentException("numItems<=0");
|
||||
}
|
||||
private List<FeedItem> saveNewItems(int numItems) {
|
||||
List<Feed> feeds = saveFeedlist(numItems, numItems, true);
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
for (Feed f : feeds) {
|
||||
items.addAll(f.getItems());
|
||||
}
|
||||
List<FeedItem> unread = new ArrayList<>();
|
||||
List<FeedItem> newItems = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
|
||||
while (unread.size() < numItems) {
|
||||
while (newItems.size() < numItems) {
|
||||
int i = random.nextInt(numItems);
|
||||
if (!unread.contains(items.get(i))) {
|
||||
if (!newItems.contains(items.get(i))) {
|
||||
FeedItem item = items.get(i);
|
||||
item.setPlayed(false);
|
||||
unread.add(item);
|
||||
item.setNew();
|
||||
newItems.add(item);
|
||||
}
|
||||
}
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setFeedItemlist(unread);
|
||||
adapter.setFeedItemlist(newItems);
|
||||
adapter.close();
|
||||
return unread;
|
||||
}
|
||||
|
||||
public void testGetUnreadItemsList() {
|
||||
final int numItems = 10;
|
||||
|
||||
List<FeedItem> unread = saveUnreadItems(numItems);
|
||||
List<FeedItem> unreadSaved = DBReader.getUnreadItemsList();
|
||||
assertNotNull(unreadSaved);
|
||||
assertTrue(unread.size() == unreadSaved.size());
|
||||
for (FeedItem item : unreadSaved) {
|
||||
assertFalse(item.isPlayed());
|
||||
}
|
||||
return newItems;
|
||||
}
|
||||
|
||||
public void testGetNewItemIds() {
|
||||
final int numItems = 10;
|
||||
|
||||
List<FeedItem> unread = saveUnreadItems(numItems);
|
||||
long[] unreadIds = new long[unread.size()];
|
||||
for (int i = 0; i < unread.size(); i++) {
|
||||
unreadIds[i] = unread.get(i).getId();
|
||||
List<FeedItem> newItems = saveNewItems(numItems);
|
||||
long[] unreadIds = new long[newItems.size()];
|
||||
for (int i = 0; i < newItems.size(); i++) {
|
||||
unreadIds[i] = newItems.get(i).getId();
|
||||
}
|
||||
List<FeedItem> unreadSaved = DBReader.getUnreadItemsList();
|
||||
assertNotNull(unreadSaved);
|
||||
assertTrue(unread.size() == unreadSaved.size());
|
||||
for(int i=0; i < unreadSaved.size(); i++) {
|
||||
long savedId = unreadSaved.get(i).getId();
|
||||
List<FeedItem> newItemsSaved = DBReader.getNewItemsList();
|
||||
assertNotNull(newItemsSaved);
|
||||
assertTrue(newItems.size() == newItemsSaved.size());
|
||||
for(int i=0; i < newItemsSaved.size(); i++) {
|
||||
long savedId = newItemsSaved.get(i).getId();
|
||||
boolean found = false;
|
||||
for (long id : unreadIds) {
|
||||
if (id == savedId) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public class DBTestUtils {
|
|||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
for (int i = 0; i < numFeeds; i++) {
|
||||
Feed f = new Feed(0, null, "feed " + i, "link" + i, "descr", null, null,
|
||||
Feed f = new Feed(0, null, "feed " + i, null, "link" + i, "descr", null, null,
|
||||
null, null, "id" + i, null, null, "url" + i, false, new FlattrStatus(), false, null, null, false);
|
||||
f.setItems(new ArrayList<>());
|
||||
for (int j = 0; j < numItems; j++) {
|
||||
|
|
|
@ -138,7 +138,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
|
|||
ListView list = (ListView) solo.getView(R.id.nav_list);
|
||||
for (int i = 0; i < uiTestUtils.hostedFeeds.size(); i++) {
|
||||
Feed f = uiTestUtils.hostedFeeds.get(i);
|
||||
solo.clickOnScreen(50, 50); // open nav drawer
|
||||
openNavDrawer();
|
||||
solo.scrollListToLine(list, i);
|
||||
solo.clickOnText(f.getTitle());
|
||||
solo.waitForView(android.R.id.list);
|
||||
|
|
|
@ -245,10 +245,10 @@ public class PlaybackSonicTest extends ActivityInstrumentationTestCase2<MainActi
|
|||
}, Timeout.getSmallTimeout());
|
||||
assertTrue(startedPlaying);
|
||||
|
||||
boolean stoppedPlaying = solo.waitForCondition(() -> {
|
||||
return uiTestUtils.getCurrentMedia(getActivity()) == null
|
||||
|| uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId;
|
||||
}, Timeout.getLargeTimeout());
|
||||
boolean stoppedPlaying = solo.waitForCondition(() ->
|
||||
uiTestUtils.getCurrentMedia(getActivity()) == null
|
||||
|| uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId
|
||||
, Timeout.getLargeTimeout());
|
||||
assertTrue(stoppedPlaying);
|
||||
|
||||
startLocalPlayback();
|
||||
|
|
|
@ -236,10 +236,9 @@ public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity>
|
|||
}, Timeout.getSmallTimeout());
|
||||
assertTrue(startedPlaying);
|
||||
|
||||
boolean stoppedPlaying = solo.waitForCondition(() -> {
|
||||
return uiTestUtils.getCurrentMedia(getActivity()) == null
|
||||
|| uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId;
|
||||
}, Timeout.getLargeTimeout());
|
||||
boolean stoppedPlaying = solo.waitForCondition(() ->
|
||||
uiTestUtils.getCurrentMedia(getActivity()) == null
|
||||
|| uiTestUtils.getCurrentMedia(getActivity()).getId() != mediaId, Timeout.getLargeTimeout());
|
||||
assertTrue(stoppedPlaying);
|
||||
|
||||
startLocalPlayback();
|
||||
|
|
|
@ -3,10 +3,12 @@ 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
|
@ -362,4 +364,48 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
|||
Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
|
||||
public void testRewindChange() {
|
||||
int seconds = UserPreferences.getRewindSecs();
|
||||
int deltas[] = res.getIntArray(R.array.seek_delta_values);
|
||||
|
||||
solo.clickOnText(solo.getString(R.string.pref_rewind));
|
||||
solo.waitForDialogToOpen();
|
||||
|
||||
int currentIndex = Arrays.binarySearch(deltas, seconds);
|
||||
assertTrue(currentIndex >= 0 && currentIndex < deltas.length); // found?
|
||||
|
||||
// Find next value (wrapping around to next)
|
||||
int newIndex = (currentIndex + 1) % deltas.length;
|
||||
|
||||
solo.clickOnText(String.valueOf(deltas[newIndex]) + " seconds");
|
||||
solo.clickOnButton("Confirm");
|
||||
|
||||
solo.waitForDialogToClose();
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getRewindSecs() == deltas[newIndex],
|
||||
Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testFastForwardChange() {
|
||||
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);
|
||||
|
||||
solo.clickOnText(solo.getString(R.string.pref_fast_forward));
|
||||
solo.waitForDialogToOpen();
|
||||
|
||||
int currentIndex = Arrays.binarySearch(deltas, seconds);
|
||||
assertTrue(currentIndex >= 0 && currentIndex < deltas.length); // found?
|
||||
|
||||
// Find next value (wrapping around to next)
|
||||
int newIndex = (currentIndex + 1) % deltas.length;
|
||||
|
||||
solo.clickOnText(String.valueOf(deltas[newIndex]) + " seconds");
|
||||
solo.clickOnButton("Confirm");
|
||||
|
||||
solo.waitForDialogToClose();
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getFastForwardSecs() == deltas[newIndex],
|
||||
Timeout.getLargeTimeout()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,16 @@ public class FilenameGeneratorTest extends AndroidTestCase {
|
|||
createFiles(result);
|
||||
}
|
||||
|
||||
public void testFeedTitleContainsApostrophe() {
|
||||
String result = FileNameGenerator.generateFileName("Feed's Title ...");
|
||||
assertEquals("Feeds Title", result);
|
||||
}
|
||||
|
||||
public void testFeedTitleContainsDash() {
|
||||
String result = FileNameGenerator.generateFileName("Left - Right");
|
||||
assertEquals("Left Right", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if files can be created.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* Activity that allows for showing the MediaRouter button whenever there's a cast device in the
|
||||
* network.
|
||||
*/
|
||||
public abstract class CastEnabledActivity extends AppCompatActivity {
|
||||
// implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
public static final String TAG = "CastEnabledActivity";
|
||||
|
||||
// protected CastManager castManager;
|
||||
// protected SwitchableMediaRouteActionProvider mediaRouteActionProvider;
|
||||
// private final CastButtonVisibilityManager castButtonVisibilityManager = new CastButtonVisibilityManager();
|
||||
//
|
||||
// @Override
|
||||
// protected void onCreate(Bundle savedInstanceState) {
|
||||
// super.onCreate(savedInstanceState);
|
||||
//
|
||||
// PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).
|
||||
// registerOnSharedPreferenceChangeListener(this);
|
||||
//
|
||||
// castManager = CastManager.getInstance();
|
||||
// castManager.addCastConsumer(castConsumer);
|
||||
// castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
|
||||
// onCastConnectionChanged(castManager.isConnected());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onDestroy() {
|
||||
// PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
|
||||
// .unregisterOnSharedPreferenceChangeListener(this);
|
||||
// castManager.removeCastConsumer(castConsumer);
|
||||
// super.onDestroy();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// @CallSuper
|
||||
// public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// super.onCreateOptionsMenu(menu);
|
||||
// getMenuInflater().inflate(R.menu.cast_enabled, menu);
|
||||
// castButtonVisibilityManager.setMenu(menu);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// @CallSuper
|
||||
// public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
// super.onPrepareOptionsMenu(menu);
|
||||
// mediaRouteActionProvider = castManager
|
||||
// .addMediaRouterButton(menu.findItem(R.id.media_route_menu_item));
|
||||
// mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable());
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onResume() {
|
||||
// super.onResume();
|
||||
// castButtonVisibilityManager.setResumed(true);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onPause() {
|
||||
// super.onPause();
|
||||
// castButtonVisibilityManager.setResumed(false);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
// if (UserPreferences.PREF_CAST_ENABLED.equals(key)) {
|
||||
// boolean newValue = UserPreferences.isCastEnabled();
|
||||
// Log.d(TAG, "onSharedPreferenceChanged(), isCastEnabled set to " + newValue);
|
||||
// castButtonVisibilityManager.setPrefEnabled(newValue);
|
||||
// // PlaybackService has its own listener, so if it's active we don't have to take action here.
|
||||
// if (!newValue && !PlaybackService.isRunning) {
|
||||
// CastManager.getInstance().disconnect();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// CastConsumer castConsumer = new DefaultCastConsumer() {
|
||||
// @Override
|
||||
// public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) {
|
||||
// onCastConnectionChanged(true);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onDisconnected() {
|
||||
// onCastConnectionChanged(false);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// private void onCastConnectionChanged(boolean connected) {
|
||||
// if (connected) {
|
||||
// castButtonVisibilityManager.onConnected();
|
||||
// setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
|
||||
// } else {
|
||||
// castButtonVisibilityManager.onDisconnected();
|
||||
// setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Should be called by any activity or fragment for which the cast button should be shown.
|
||||
// *
|
||||
// * @param showAsAction refer to {@link MenuItem#setShowAsAction(int)}
|
||||
// */
|
||||
public final void requestCastButton(int showAsAction) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// private class CastButtonVisibilityManager {
|
||||
// private volatile boolean prefEnabled = false;
|
||||
// private volatile boolean viewRequested = false;
|
||||
// private volatile boolean resumed = false;
|
||||
// private volatile boolean connected = false;
|
||||
// private volatile int showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
|
||||
// private Menu menu;
|
||||
//
|
||||
// public synchronized void setPrefEnabled(boolean newValue) {
|
||||
// if (prefEnabled != newValue && resumed && (viewRequested || connected)) {
|
||||
// if (newValue) {
|
||||
// castManager.incrementUiCounter();
|
||||
// } else {
|
||||
// castManager.decrementUiCounter();
|
||||
// }
|
||||
// }
|
||||
// prefEnabled = newValue;
|
||||
// if (mediaRouteActionProvider != null) {
|
||||
// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public synchronized void setResumed(boolean newValue) {
|
||||
// if (resumed == newValue) {
|
||||
// Log.e(TAG, "resumed should never change to the same value");
|
||||
// return;
|
||||
// }
|
||||
// resumed = newValue;
|
||||
// if (prefEnabled && (viewRequested || connected)) {
|
||||
// if (resumed) {
|
||||
// castManager.incrementUiCounter();
|
||||
// } else {
|
||||
// castManager.decrementUiCounter();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public synchronized void setViewRequested(boolean newValue) {
|
||||
// if (viewRequested != newValue && resumed && prefEnabled && !connected) {
|
||||
// if (newValue) {
|
||||
// castManager.incrementUiCounter();
|
||||
// } else {
|
||||
// castManager.decrementUiCounter();
|
||||
// }
|
||||
// }
|
||||
// viewRequested = newValue;
|
||||
// if (mediaRouteActionProvider != null) {
|
||||
// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public synchronized void setConnected(boolean newValue) {
|
||||
// if (connected != newValue && resumed && prefEnabled && !prefEnabled) {
|
||||
// if (newValue) {
|
||||
// castManager.incrementUiCounter();
|
||||
// } else {
|
||||
// castManager.decrementUiCounter();
|
||||
// }
|
||||
// }
|
||||
// connected = newValue;
|
||||
// if (mediaRouteActionProvider != null) {
|
||||
// mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public synchronized boolean shouldEnable() {
|
||||
// return prefEnabled && viewRequested;
|
||||
// }
|
||||
//
|
||||
// public void setMenu(Menu menu) {
|
||||
// setViewRequested(false);
|
||||
// showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
|
||||
// this.menu = menu;
|
||||
// setShowAsAction();
|
||||
// }
|
||||
//
|
||||
// public void requestCastButton(int showAsAction) {
|
||||
// setViewRequested(true);
|
||||
// this.showAsAction = showAsAction;
|
||||
// setShowAsAction();
|
||||
// }
|
||||
//
|
||||
// public void onConnected() {
|
||||
// setConnected(true);
|
||||
// setShowAsAction();
|
||||
// }
|
||||
//
|
||||
// public void onDisconnected() {
|
||||
// setConnected(false);
|
||||
// setShowAsAction();
|
||||
// }
|
||||
//
|
||||
// private void setShowAsAction() {
|
||||
// if (menu == null) {
|
||||
// Log.d(TAG, "setShowAsAction() without a menu");
|
||||
// return;
|
||||
// }
|
||||
// MenuItem item = menu.findItem(R.id.media_route_menu_item);
|
||||
// if (item == null) {
|
||||
// Log.e(TAG, "setShowAsAction(), but cast button not inflated");
|
||||
// return;
|
||||
// }
|
||||
// MenuItemCompat.setShowAsAction(item, connected? MenuItem.SHOW_AS_ACTION_ALWAYS : showAsAction);
|
||||
// }
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package de.danoeh.antennapod.config;
|
||||
|
||||
import de.danoeh.antennapod.core.CastCallbacks;
|
||||
|
||||
public class CastCallbackImpl implements CastCallbacks {
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package de.danoeh.antennapod.preferences;
|
||||
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
|
||||
/**
|
||||
* Implements functions from PreferenceController that are flavor dependent.
|
||||
*/
|
||||
public class PreferenceControllerFlavorHelper {
|
||||
|
||||
static void setupFlavoredUI(PreferenceController.PreferenceUI ui) {
|
||||
ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setEnabled(false);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.danoeh.antennapod"
|
||||
android:versionCode="1060009"
|
||||
android:versionName="1.6.0.9">
|
||||
android:installLocation="auto"
|
||||
android:versionCode="1060400"
|
||||
android:versionName="1.6.4.0">
|
||||
<!--
|
||||
Version code schema:
|
||||
"1.2.3-SNAPSHOT" -> 1020300
|
||||
|
@ -37,23 +38,35 @@
|
|||
android:backupAgent=".core.backup.OpmlBackupAgent"
|
||||
android:restoreAnyVersion="true"
|
||||
android:logo="@drawable/ic_launcher">
|
||||
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||
android:resource="@drawable/ic_notification" />
|
||||
<meta-data
|
||||
android:name="com.google.android.backup.api_key"
|
||||
android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.version"
|
||||
android:value="@integer/google_play_services_version" />
|
||||
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:name=".activity.SplashActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:launchMode="singleTask"
|
||||
android:label="@string/app_name">
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.AntennaPod.Dark.Splash">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name=
|
||||
"android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<category android:name=
|
||||
"android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:launchMode="singleTask"
|
||||
android:label="@string/app_name">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.AudioplayerActivity"
|
||||
|
@ -85,7 +98,7 @@
|
|||
|
||||
<activity
|
||||
android:name=".activity.PreferenceActivityGingerbread"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/settings_label">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
|
@ -94,7 +107,7 @@
|
|||
|
||||
<activity
|
||||
android:name=".activity.PreferenceActivity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/settings_label">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
|
@ -150,6 +163,7 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".activity.AboutActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/about_pref">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
|
@ -164,12 +178,12 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".activity.OpmlImportFromPathActivity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/opml_import_label">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.OpmlImportFromIntentActivity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/opml_import_label">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
@ -177,16 +191,30 @@
|
|||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data
|
||||
android:host="*"
|
||||
android:pathPattern=".*\\.opml"
|
||||
android:scheme="file"
|
||||
android:mimeType="*/*"/>
|
||||
<data
|
||||
android:host="*"
|
||||
android:pathPattern=".*\\.opml"
|
||||
android:scheme="content"
|
||||
android:mimeType="*/*"/>
|
||||
<data android:mimeType="text/xml"/>
|
||||
<data android:mimeType="text/x-opml"/>
|
||||
<data android:mimeType="application/xml"/>
|
||||
<data android:mimeType="application/octet-stream"/>
|
||||
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="content"/>
|
||||
|
||||
<data android:host="*"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:mimeType="text/xml"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
<data android:mimeType="text/x-opml"/>
|
||||
<data android:mimeType="application/xml"/>
|
||||
<data android:mimeType="application/octet-stream"/>
|
||||
|
||||
<data android:scheme="http"/>
|
||||
<data android:scheme="https"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
|
@ -221,7 +249,7 @@
|
|||
|
||||
<activity
|
||||
android:name=".activity.OnlineFeedViewActivity"
|
||||
android:configChanges="orientation"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/add_feed_label">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
|
@ -240,6 +268,7 @@
|
|||
<data android:host="*"/>
|
||||
<data android:pathPattern=".*\\.xml"/>
|
||||
<data android:pathPattern=".*\\.rss"/>
|
||||
<data android:pathPattern=".*\\.atom"/>
|
||||
</intent-filter>
|
||||
|
||||
<!-- Feedburner URLs -->
|
||||
|
@ -346,6 +375,10 @@
|
|||
<meta-data
|
||||
android:name="de.danoeh.antennapod.core.glide.ApGlideModule"
|
||||
android:value="GlideModule" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.car.application"
|
||||
android:resource="@xml/automotive_app_desc"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -3,6 +3,7 @@ package de.danoeh.antennapod;
|
|||
import android.app.Application;
|
||||
import android.os.Build;
|
||||
import android.os.StrictMode;
|
||||
import android.support.multidex.MultiDexApplication;
|
||||
|
||||
import com.joanzapata.iconify.Iconify;
|
||||
import com.joanzapata.iconify.fonts.FontAwesomeModule;
|
||||
|
@ -13,7 +14,7 @@ import de.danoeh.antennapod.core.feed.EventDistributor;
|
|||
import de.danoeh.antennapod.spa.SPAUtil;
|
||||
|
||||
/** Main application class. */
|
||||
public class PodcastApp extends Application {
|
||||
public class PodcastApp extends MultiDexApplication {
|
||||
|
||||
// make sure that ClientConfigurator executes its static code
|
||||
static {
|
||||
|
|
|
@ -124,12 +124,11 @@ public class AboutActivity extends AppCompatActivity {
|
|||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(webviewData -> {
|
||||
webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html",
|
||||
"utf-8", "about:blank");
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
.subscribe(
|
||||
webviewData ->
|
||||
webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html", "utf-8", "about:blank"),
|
||||
error -> Log.e(TAG, Log.getStackTraceString(error))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -50,10 +50,10 @@ public class CastplayerActivity extends MediaplayerInfoActivity {
|
|||
if (butPlaybackSpeed != null) {
|
||||
butPlaybackSpeed.setVisibility(View.GONE);
|
||||
}
|
||||
if (butCastDisconnect != null) {
|
||||
butCastDisconnect.setOnClickListener(v -> castManager.disconnect());
|
||||
butCastDisconnect.setVisibility(View.VISIBLE);
|
||||
}
|
||||
// if (butCastDisconnect != null) {
|
||||
// butCastDisconnect.setOnClickListener(v -> castManager.disconnect());
|
||||
// butCastDisconnect.setVisibility(View.VISIBLE);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -89,9 +89,7 @@ public class DirectoryChooserActivity extends AppCompatActivity {
|
|||
adb.setTitle(R.string.folder_not_empty_dialog_title);
|
||||
adb.setMessage(R.string.folder_not_empty_dialog_msg);
|
||||
adb.setNegativeButton(R.string.cancel_label,
|
||||
(dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
(dialog, which) -> dialog.dismiss());
|
||||
adb.setPositiveButton(R.string.confirm_label,
|
||||
(dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
|
@ -291,9 +289,7 @@ public class DirectoryChooserActivity extends AppCompatActivity {
|
|||
builder.setMessage(String.format(getString(R.string.create_folder_msg),
|
||||
CREATE_DIRECTORY_NAME));
|
||||
builder.setNegativeButton(R.string.cancel_label,
|
||||
(dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
(dialog, which) -> dialog.dismiss());
|
||||
builder.setPositiveButton(R.string.confirm_label,
|
||||
(dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
|
|
|
@ -5,10 +5,10 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
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;
|
||||
|
@ -28,6 +28,10 @@ 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;
|
||||
|
@ -41,23 +45,29 @@ 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 rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Displays information about a feed.
|
||||
*/
|
||||
public class FeedInfoActivity extends ActionBarActivity {
|
||||
private static final String TAG = "FeedInfoActivity";
|
||||
private boolean autoDeleteChanged = false;
|
||||
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;
|
||||
private TextView txtvTitle;
|
||||
private TextView txtvDescription;
|
||||
private TextView lblLanguage;
|
||||
private TextView txtvLanguage;
|
||||
private TextView lblAuthor;
|
||||
private TextView txtvAuthor;
|
||||
private TextView txtvUrl;
|
||||
private EditText etxtUsername;
|
||||
|
@ -70,6 +80,9 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
private Spinner spnAutoDelete;
|
||||
private boolean filterInclude = true;
|
||||
|
||||
private Subscription subscription;
|
||||
|
||||
|
||||
private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -91,6 +104,40 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
}
|
||||
};
|
||||
|
||||
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());
|
||||
|
@ -102,7 +149,9 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
imgvCover = (ImageView) findViewById(R.id.imgvCover);
|
||||
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
|
||||
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);
|
||||
txtvUrl = (TextView) findViewById(R.id.txtvUrl);
|
||||
cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
|
||||
|
@ -124,48 +173,62 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
|
||||
txtvUrl.setOnClickListener(copyUrlToClipboard);
|
||||
|
||||
AsyncTask<Long, Void, Feed> loadTask = new AsyncTask<Long, Void, Feed>() {
|
||||
|
||||
@Override
|
||||
protected Feed doInBackground(Long... params) {
|
||||
return DBReader.getFeed(params[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Feed result) {
|
||||
if (result != null) {
|
||||
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;
|
||||
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();
|
||||
imgvCover.post(() -> Glide.with(FeedInfoActivity.this)
|
||||
.load(feed.getImageUri())
|
||||
Glide.with(FeedInfoActivity.this)
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(imgvCover));
|
||||
.into(imgvCover);
|
||||
|
||||
txtvTitle.setText(feed.getTitle());
|
||||
|
||||
String description = feed.getDescription();
|
||||
txtvDescription.setText((description != null) ? description.trim() : "");
|
||||
if (feed.getAuthor() != null) {
|
||||
txtvAuthor.setText(feed.getAuthor());
|
||||
if(description != null) {
|
||||
if(Feed.TYPE_ATOM1.equals(feed.getType())) {
|
||||
HtmlToPlainText formatter = new HtmlToPlainText();
|
||||
Document feedDescription = Jsoup.parse(feed.getDescription());
|
||||
description = StringUtils.trim(formatter.getPlainText(feedDescription));
|
||||
}
|
||||
} else {
|
||||
description = "";
|
||||
}
|
||||
if (feed.getLanguage() != null) {
|
||||
txtvLanguage.setText(LangUtils
|
||||
.getLanguageString(feed.getLanguage()));
|
||||
txtvDescription.setText(description);
|
||||
|
||||
if (!TextUtils.isEmpty(feed.getAuthor())) {
|
||||
txtvAuthor.setText(feed.getAuthor());
|
||||
} else {
|
||||
lblAuthor.setVisibility(View.GONE);
|
||||
txtvAuthor.setVisibility(View.GONE);
|
||||
}
|
||||
if (!TextUtils.isEmpty(feed.getLanguage())) {
|
||||
txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage()));
|
||||
} else {
|
||||
lblLanguage.setVisibility(View.GONE);
|
||||
txtvLanguage.setVisibility(View.GONE);
|
||||
}
|
||||
txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}");
|
||||
Iconify.addIcons(txtvUrl);
|
||||
Iconify.addIcons(txtvUrl);
|
||||
|
||||
cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
|
||||
cbxAutoDownload.setChecked(prefs.getAutoDownload());
|
||||
cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> {
|
||||
feed.getPreferences().setAutoDownload(checked);
|
||||
feed.savePreferences(FeedInfoActivity.this);
|
||||
feed.savePreferences();
|
||||
updateAutoDownloadSettings();
|
||||
ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this,
|
||||
feed, checked);
|
||||
|
@ -174,7 +237,7 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
cbxKeepUpdated.setChecked(prefs.getKeepUpdated());
|
||||
cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> {
|
||||
feed.getPreferences().setKeepUpdated(checked);
|
||||
feed.savePreferences(FeedInfoActivity.this);
|
||||
feed.savePreferences();
|
||||
});
|
||||
spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
@Override
|
||||
|
@ -184,15 +247,12 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
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;
|
||||
}
|
||||
|
@ -234,57 +294,12 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
|
||||
supportInvalidateOptionsMenu();
|
||||
updateAutoDownloadSettings();
|
||||
} else {
|
||||
Log.e(TAG, "Activity was started with invalid arguments");
|
||||
}
|
||||
}
|
||||
};
|
||||
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
|
||||
loadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, feedId);
|
||||
} else {
|
||||
loadTask.execute(feedId);
|
||||
}
|
||||
}, error -> {
|
||||
Log.d(TAG, Log.getStackTraceString(error));
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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 onPause() {
|
||||
super.onPause();
|
||||
|
@ -316,6 +331,14 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
@ -367,7 +390,7 @@ public class FeedInfoActivity extends ActionBarActivity {
|
|||
private final Feed feed;
|
||||
private final boolean autoDownload;
|
||||
|
||||
public ApplyToEpisodesDialog(Context context, Feed feed, 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;
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.database.DataSetObserver;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
@ -38,6 +39,7 @@ import de.danoeh.antennapod.R;
|
|||
import de.danoeh.antennapod.adapter.NavListAdapter;
|
||||
import de.danoeh.antennapod.core.asynctask.FeedRemover;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.event.MessageEvent;
|
||||
import de.danoeh.antennapod.core.event.ProgressEvent;
|
||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
|
@ -46,10 +48,13 @@ import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
|||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.core.util.Flavors;
|
||||
import de.danoeh.antennapod.core.util.StorageUtils;
|
||||
import de.danoeh.antennapod.dialog.RatingDialog;
|
||||
import de.danoeh.antennapod.dialog.RenameFeedDialog;
|
||||
import de.danoeh.antennapod.fragment.AddFeedFragment;
|
||||
import de.danoeh.antennapod.fragment.DownloadsFragment;
|
||||
import de.danoeh.antennapod.fragment.EpisodesFragment;
|
||||
|
@ -148,9 +153,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
|
||||
final FragmentManager fm = getSupportFragmentManager();
|
||||
|
||||
fm.addOnBackStackChangedListener(() -> {
|
||||
drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0);
|
||||
});
|
||||
fm.addOnBackStackChangedListener(() -> drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0));
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
|
@ -209,7 +212,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
} else {
|
||||
edit.remove(PREF_LAST_FRAGMENT_TAG);
|
||||
}
|
||||
edit.commit();
|
||||
edit.apply();
|
||||
}
|
||||
|
||||
private String getLastNavFragment() {
|
||||
|
@ -254,9 +257,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||
UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> UserPreferences.setHiddenDrawerItems(hiddenDrawerItems));
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.create().show();
|
||||
}
|
||||
|
@ -466,6 +467,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
StorageUtils.checkStorageAvailability(this);
|
||||
DBTasks.checkShouldRefreshFeeds(getApplicationContext());
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent.hasExtra(EXTRA_FEED_ID) ||
|
||||
|
@ -507,21 +509,24 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
boolean retVal = super.onCreateOptionsMenu(menu);
|
||||
switch (getLastNavFragment()) {
|
||||
case QueueFragment.TAG:
|
||||
case EpisodesFragment.TAG:
|
||||
requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
return retVal;
|
||||
case DownloadsFragment.TAG:
|
||||
case PlaybackHistoryFragment.TAG:
|
||||
case AddFeedFragment.TAG:
|
||||
case SubscriptionFragment.TAG:
|
||||
return retVal;
|
||||
default:
|
||||
requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
return retVal;
|
||||
if (Flavors.FLAVOR == Flavors.PLAY) {
|
||||
switch (getLastNavFragment()) {
|
||||
case QueueFragment.TAG:
|
||||
case EpisodesFragment.TAG:
|
||||
requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
return retVal;
|
||||
case DownloadsFragment.TAG:
|
||||
case PlaybackHistoryFragment.TAG:
|
||||
case AddFeedFragment.TAG:
|
||||
case SubscriptionFragment.TAG:
|
||||
return retVal;
|
||||
default:
|
||||
requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
return retVal;
|
||||
}
|
||||
} else {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -573,6 +578,9 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
case R.id.mark_all_read_item:
|
||||
DBWriter.markFeedRead(feed.getId());
|
||||
return true;
|
||||
case R.id.rename_item:
|
||||
new RenameFeedDialog(this, feed).show();
|
||||
return true;
|
||||
case R.id.remove_item:
|
||||
final FeedRemover remover = new FeedRemover(this, feed) {
|
||||
@Override
|
||||
|
@ -585,7 +593,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
};
|
||||
ConfirmationDialog conDialog = new ConfirmationDialog(this,
|
||||
R.string.remove_feed_label,
|
||||
R.string.feed_delete_confirmation_msg) {
|
||||
getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
|
||||
@Override
|
||||
public void onConfirmButtonPressed(
|
||||
DialogInterface dialog) {
|
||||
|
@ -699,9 +707,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
if (handleIntent) {
|
||||
handleNavIntent();
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
public void onEvent(QueueEvent event) {
|
||||
|
@ -733,6 +739,18 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
|
|||
}
|
||||
}
|
||||
|
||||
public void onEventMainThread(MessageEvent event) {
|
||||
Log.d(TAG, "onEvent(" + event + ")");
|
||||
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.show();
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.TypedArray;
|
||||
|
@ -9,6 +10,7 @@ import android.graphics.PixelFormat;
|
|||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
|
@ -39,8 +41,10 @@ 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.Flavors;
|
||||
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.playback.MediaPlayerError;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||
|
@ -48,6 +52,8 @@ import de.danoeh.antennapod.dialog.SleepTimerDialog;
|
|||
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||
import rx.Observable;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.functions.Action1;
|
||||
import rx.functions.Func1;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
|
||||
|
@ -177,6 +183,13 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
};
|
||||
}
|
||||
|
||||
protected static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
|
||||
return activity.txtvFF;
|
||||
}
|
||||
protected static TextView getTxtvRevFromActivity(MediaplayerActivity activity) {
|
||||
return activity.txtvRev;
|
||||
}
|
||||
|
||||
protected void onSetSpeedAbilityChanged() {
|
||||
Log.d(TAG, "onSetSpeedAbilityChanged()");
|
||||
updatePlaybackSpeedButton();
|
||||
|
@ -281,7 +294,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
if (Flavors.FLAVOR == Flavors.PLAY) {
|
||||
requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
}
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.mediaplayer, menu);
|
||||
return true;
|
||||
|
@ -294,10 +309,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
return false;
|
||||
}
|
||||
Playable media = controller.getMedia();
|
||||
boolean isFeedMedia = media != null && (media instanceof FeedMedia);
|
||||
|
||||
menu.findItem(R.id.support_item).setVisible(
|
||||
media != null && media.getPaymentLink() != null &&
|
||||
(media instanceof FeedMedia) &&
|
||||
menu.findItem(R.id.support_item).setVisible(isFeedMedia && media.getPaymentLink() != null &&
|
||||
((FeedMedia) media).getItem() != null &&
|
||||
((FeedMedia) media).getItem().getFlattrStatus().flattrable()
|
||||
);
|
||||
|
@ -305,20 +319,21 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
boolean hasWebsiteLink = media != null && media.getWebsiteLink() != null;
|
||||
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink);
|
||||
|
||||
boolean isItemAndHasLink = media != null && (media instanceof FeedMedia) &&
|
||||
boolean isItemAndHasLink = isFeedMedia &&
|
||||
((FeedMedia) media).getItem() != null && ((FeedMedia) media).getItem().getLink() != null;
|
||||
menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink);
|
||||
menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink);
|
||||
|
||||
boolean isItemHasDownloadLink = media != null && (media instanceof FeedMedia) && ((FeedMedia) media).getDownload_url() != null;
|
||||
boolean isItemHasDownloadLink = isFeedMedia && ((FeedMedia) media).getDownload_url() != null;
|
||||
menu.findItem(R.id.share_download_url_item).setVisible(isItemHasDownloadLink);
|
||||
menu.findItem(R.id.share_download_url_with_position_item).setVisible(isItemHasDownloadLink);
|
||||
menu.findItem(R.id.share_file).setVisible(isFeedMedia && ((FeedMedia) media).fileExists());
|
||||
|
||||
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink);
|
||||
|
||||
menu.findItem(R.id.add_to_favorites_item).setVisible(false);
|
||||
menu.findItem(R.id.remove_from_favorites_item).setVisible(false);
|
||||
if(media != null && media instanceof FeedMedia) {
|
||||
if (isFeedMedia) {
|
||||
menu.findItem(R.id.add_to_favorites_item).setVisible(!isFavorite);
|
||||
menu.findItem(R.id.remove_from_favorites_item).setVisible(isFavorite);
|
||||
}
|
||||
|
@ -559,6 +574,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true);
|
||||
}
|
||||
break;
|
||||
case R.id.share_file:
|
||||
if (media instanceof FeedMedia) {
|
||||
ShareUtils.shareFeedItemFile(this, ((FeedMedia) media));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -627,17 +647,16 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
*/
|
||||
protected 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);
|
||||
if (media != null) {
|
||||
onPositionObserverUpdate();
|
||||
checkFavorite();
|
||||
updatePlaybackSpeedButton();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
onPositionObserverUpdate();
|
||||
checkFavorite();
|
||||
updatePlaybackSpeedButton();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updatePlaybackSpeedButton() {
|
||||
|
@ -648,6 +667,91 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
// 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 {
|
||||
SKIP_FORWARD(
|
||||
UserPreferences::getFastForwardSecs,
|
||||
MediaplayerActivity::getTxtvFFFromActivity,
|
||||
UserPreferences::setFastForwardSecs,
|
||||
R.string.pref_fast_forward),
|
||||
SKIP_REWIND(UserPreferences::getRewindSecs,
|
||||
MediaplayerActivity::getTxtvRevFromActivity,
|
||||
UserPreferences::setRewindSecs,
|
||||
R.string.pref_rewind);
|
||||
|
||||
private final Supplier<Integer> getPrefSecsFn;
|
||||
private final Func1<MediaplayerActivity, TextView> getTextViewFn;
|
||||
private final Action1<Integer> setPrefSecsFn;
|
||||
private final int titleResourceID;
|
||||
|
||||
/**
|
||||
* Constructor for skip direction enum. Stores references to utility functions and resource
|
||||
* id's that vary dependending on the direction.
|
||||
*
|
||||
* @param getPrefSecsFn Handle to function that retrieves current seconds of the skip delta
|
||||
* @param getTextViewFn Handle to function that gets the TextView which displays the current skip delta value
|
||||
* @param setPrefSecsFn Handle to function that sets the preference (setting) for the skip delta value (and optionally updates the button label with the current values)
|
||||
* @param titleResourceID ID of the resource string with the title for a view
|
||||
*/
|
||||
SkipDirection(Supplier<Integer> getPrefSecsFn, Func1<MediaplayerActivity, TextView> getTextViewFn, Action1<Integer> setPrefSecsFn, int titleResourceID) {
|
||||
this.getPrefSecsFn = getPrefSecsFn;
|
||||
this.getTextViewFn = getTextViewFn;
|
||||
this.setPrefSecsFn = setPrefSecsFn;
|
||||
this.titleResourceID = titleResourceID;
|
||||
}
|
||||
|
||||
|
||||
public int getPrefSkipSeconds() {
|
||||
return(getPrefSecsFn.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates preferences for a forward or backward skip depending on the direction of the instance, optionally updating the UI.
|
||||
*
|
||||
* @param seconds Number of seconds to set the preference associated with the direction of the instance.
|
||||
* @param activity MediaplyerActivity that contains textview to update the display of the skip delta setting (or null if nothing to update)
|
||||
*/
|
||||
public void setPrefSkipSeconds(int seconds, @Nullable Activity activity) {
|
||||
setPrefSecsFn.call(seconds);
|
||||
|
||||
if (activity != null && activity instanceof MediaplayerActivity) {
|
||||
TextView tv = getTextViewFn.call((MediaplayerActivity)activity);
|
||||
if (tv != null) tv.setText(String.valueOf(seconds));
|
||||
}
|
||||
}
|
||||
public int getTitleResourceID() {
|
||||
return titleResourceID;
|
||||
}
|
||||
}
|
||||
|
||||
static public void showSkipPreference(Activity activity, SkipDirection direction) {
|
||||
int checked = 0;
|
||||
int skipSecs = direction.getPrefSkipSeconds();
|
||||
final int[] values = activity.getResources().getIntArray(R.array.seek_delta_values);
|
||||
final String[] choices = new String[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (skipSecs == values[i]) {
|
||||
checked = i;
|
||||
}
|
||||
choices[i] = String.valueOf(values[i]) + " " + activity.getString(R.string.time_seconds);
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle(direction.getTitleResourceID());
|
||||
builder.setSingleChoiceItems(choices, checked, null);
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||
int choice = ((AlertDialog)dialog).getListView().getCheckedItemPosition();
|
||||
if (choice < 0 || choice >= values.length) {
|
||||
System.err.printf("Choice in showSkipPreference is out of bounds %d", choice);
|
||||
} else {
|
||||
direction.setPrefSkipSeconds(values[choice], activity);
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
protected void setupGUI() {
|
||||
setContentView(getContentViewResourceId());
|
||||
|
@ -690,7 +794,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
butFF = (ImageButton) findViewById(R.id.butFF);
|
||||
txtvFF = (TextView) findViewById(R.id.txtvFF);
|
||||
if (txtvFF != null) {
|
||||
txtvFF.setText(String.valueOf(UserPreferences.getFastFowardSecs()));
|
||||
txtvFF.setText(String.valueOf(UserPreferences.getFastForwardSecs()));
|
||||
}
|
||||
butSkip = (ImageButton) findViewById(R.id.butSkip);
|
||||
|
||||
|
@ -702,39 +806,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
|
||||
if (butRev != null) {
|
||||
butRev.setOnClickListener(v -> onRewind());
|
||||
butRev.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
|
||||
int choice;
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
int checked = 0;
|
||||
int rewindSecs = UserPreferences.getRewindSecs();
|
||||
final int[] values = getResources().getIntArray(R.array.seek_delta_values);
|
||||
final String[] choices = new String[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (rewindSecs == values[i]) {
|
||||
checked = i;
|
||||
}
|
||||
choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
|
||||
}
|
||||
choice = values[checked];
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
|
||||
builder.setTitle(R.string.pref_rewind);
|
||||
builder.setSingleChoiceItems(choices, checked,
|
||||
(dialog, which) -> {
|
||||
choice = values[which];
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||
UserPreferences.setPrefRewindSecs(choice);
|
||||
if(txtvRev != null){
|
||||
txtvRev.setText(String.valueOf(choice));
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
return true;
|
||||
}
|
||||
butRev.setOnLongClickListener(v -> {
|
||||
showSkipPreference(MediaplayerActivity.this, SkipDirection.SKIP_REWIND);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -742,39 +816,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
|
||||
if (butFF != null) {
|
||||
butFF.setOnClickListener(v -> onFastForward());
|
||||
butFF.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
|
||||
int choice;
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
int checked = 0;
|
||||
int rewindSecs = UserPreferences.getFastFowardSecs();
|
||||
final int[] values = getResources().getIntArray(R.array.seek_delta_values);
|
||||
final String[] choices = new String[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (rewindSecs == values[i]) {
|
||||
checked = i;
|
||||
}
|
||||
choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
|
||||
}
|
||||
choice = values[checked];
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
|
||||
builder.setTitle(R.string.pref_fast_forward);
|
||||
builder.setSingleChoiceItems(choices, checked,
|
||||
(dialog, which) -> {
|
||||
choice = values[which];
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||
UserPreferences.setPrefFastForwardSecs(choice);
|
||||
if(txtvFF != null) {
|
||||
txtvFF.setText(String.valueOf(choice));
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
return true;
|
||||
}
|
||||
butFF.setOnLongClickListener(v -> {
|
||||
showSkipPreference(MediaplayerActivity.this, SkipDirection.SKIP_FORWARD);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -803,7 +847,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
return;
|
||||
}
|
||||
int curr = controller.getPosition();
|
||||
controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000);
|
||||
controller.seekTo(curr + UserPreferences.getFastForwardSecs() * 1000);
|
||||
}
|
||||
|
||||
protected abstract int getContentViewResourceId();
|
||||
|
@ -865,10 +909,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
|
|||
isFavorite = isFav;
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
}
|
||||
);
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.content.res.Configuration;
|
|||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
|
@ -36,6 +37,7 @@ import de.danoeh.antennapod.adapter.ChaptersListAdapter;
|
|||
import de.danoeh.antennapod.adapter.NavListAdapter;
|
||||
import de.danoeh.antennapod.core.asynctask.FeedRemover;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.event.MessageEvent;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
|
@ -43,9 +45,11 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
|
|||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||
import de.danoeh.antennapod.dialog.RenameFeedDialog;
|
||||
import de.danoeh.antennapod.fragment.AddFeedFragment;
|
||||
import de.danoeh.antennapod.fragment.ChaptersFragment;
|
||||
import de.danoeh.antennapod.fragment.CoverFragment;
|
||||
|
@ -57,6 +61,7 @@ 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;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
|
@ -101,6 +106,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
|||
|
||||
private Subscription subscription;
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
@ -168,8 +179,10 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
|||
pagerAdapter.onMediaChanged(media);
|
||||
pagerAdapter.setController(controller);
|
||||
}
|
||||
DBTasks.checkShouldRefreshFeeds(getApplicationContext());
|
||||
|
||||
EventDistributor.getInstance().register(contentUpdate);
|
||||
EventBus.getDefault().register(this);
|
||||
loadData();
|
||||
}
|
||||
|
||||
|
@ -277,7 +290,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
|||
if (!super.loadMediaInfo()) {
|
||||
return false;
|
||||
}
|
||||
if(controller.getMedia() != media) {
|
||||
if(controller != null && controller.getMedia() != media) {
|
||||
media = controller.getMedia();
|
||||
pagerAdapter.onMediaChanged(media);
|
||||
}
|
||||
|
@ -370,6 +383,9 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
|||
case R.id.mark_all_read_item:
|
||||
DBWriter.markFeedRead(feed.getId());
|
||||
return true;
|
||||
case R.id.rename_item:
|
||||
new RenameFeedDialog(this, feed).show();
|
||||
return true;
|
||||
case R.id.remove_item:
|
||||
final FeedRemover remover = new FeedRemover(this, feed) {
|
||||
@Override
|
||||
|
@ -379,7 +395,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
|||
};
|
||||
ConfirmationDialog conDialog = new ConfirmationDialog(this,
|
||||
R.string.remove_feed_label,
|
||||
R.string.feed_delete_confirmation_msg) {
|
||||
getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
|
||||
@Override
|
||||
public void onConfirmButtonPressed(
|
||||
DialogInterface dialog) {
|
||||
|
@ -443,9 +459,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
|||
hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||
UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> UserPreferences.setHiddenDrawerItems(hiddenDrawerItems));
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.create().show();
|
||||
}
|
||||
|
@ -461,12 +475,20 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
|
|||
if (navAdapter != null) {
|
||||
navAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
|
||||
public void onEventMainThread(MessageEvent event) {
|
||||
Log.d(TAG, "onEvent(" + event + ")");
|
||||
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.show();
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import com.bumptech.glide.Glide;
|
|||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.examples.HtmlToPlainText;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -63,6 +62,7 @@ import de.danoeh.antennapod.core.util.FileNameGenerator;
|
|||
import de.danoeh.antennapod.core.util.StorageUtils;
|
||||
import de.danoeh.antennapod.core.util.URLChecker;
|
||||
import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;
|
||||
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
|
||||
import de.danoeh.antennapod.dialog.AuthenticationDialog;
|
||||
import de.greenrobot.event.EventBus;
|
||||
import rx.Observable;
|
||||
|
@ -81,17 +81,12 @@ import rx.schedulers.Schedulers;
|
|||
*/
|
||||
public class OnlineFeedViewActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "OnlineFeedViewActivity";
|
||||
|
||||
public static final String ARG_FEEDURL = "arg.feedurl";
|
||||
|
||||
// Optional argument: specify a title for the actionbar.
|
||||
public static final String ARG_TITLE = "title";
|
||||
|
||||
private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE;
|
||||
|
||||
public 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;
|
||||
private Feed feed;
|
||||
private String selectedDownloadUrl;
|
||||
|
@ -106,22 +101,19 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
|||
private Subscription download;
|
||||
private Subscription parser;
|
||||
private Subscription updater;
|
||||
|
||||
public void onEventMainThread(DownloadEvent event) {
|
||||
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
||||
setSubscribeButtonState(feed);
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener listener = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) {
|
||||
updater = Observable.fromCallable(() -> DBReader.getFeedList())
|
||||
updater = Observable.fromCallable(DBReader::getFeedList)
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(feeds -> {
|
||||
.subscribe(
|
||||
feeds -> {
|
||||
OnlineFeedViewActivity.this.feeds = feeds;
|
||||
setSubscribeButtonState(feed);
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
}
|
||||
);
|
||||
} else if ((arg & EVENTS) != 0) {
|
||||
|
@ -130,6 +122,11 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
|||
}
|
||||
};
|
||||
|
||||
public void onEventMainThread(DownloadEvent event) {
|
||||
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
||||
setSubscribeButtonState(feed);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
|
@ -149,7 +146,7 @@ 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_new_feed_label);
|
||||
getSupportActionBar().setTitle(R.string.add_feed_label);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Activity must be started with feedurl argument!");
|
||||
}
|
||||
|
@ -281,30 +278,33 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
|||
})
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(status -> {
|
||||
if (status != null) {
|
||||
if (!status.isCancelled()) {
|
||||
if (status.isSuccessful()) {
|
||||
parseFeed();
|
||||
} else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
|
||||
if (!isFinishing() && !isPaused) {
|
||||
dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this,
|
||||
R.string.authentication_notification_title, downloader.getDownloadRequest().getSource());
|
||||
dialog.show();
|
||||
}
|
||||
} else {
|
||||
String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this);
|
||||
if (errorMsg != null && status.getReasonDetailed() != null) {
|
||||
errorMsg += " (" + status.getReasonDetailed() + ")";
|
||||
}
|
||||
showErrorDialog(errorMsg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.wtf(TAG, "DownloadStatus returned by Downloader was null");
|
||||
finish();
|
||||
}
|
||||
});
|
||||
.subscribe(this::checkDownloadResult,
|
||||
error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private void checkDownloadResult(DownloadStatus status) {
|
||||
if (status == null) {
|
||||
Log.wtf(TAG, "DownloadStatus returned by Downloader was null");
|
||||
finish();
|
||||
}
|
||||
if (status.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
if (status.isSuccessful()) {
|
||||
parseFeed();
|
||||
} else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
|
||||
if (!isFinishing() && !isPaused) {
|
||||
dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this,
|
||||
R.string.authentication_notification_title, downloader.getDownloadRequest().getSource());
|
||||
dialog.show();
|
||||
}
|
||||
} else {
|
||||
String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this);
|
||||
if (errorMsg != null && status.getReasonDetailed() != null) {
|
||||
errorMsg += " (" + status.getReasonDetailed() + ")";
|
||||
}
|
||||
showErrorDialog(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseFeed() {
|
||||
|
@ -354,14 +354,19 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
|||
* This method is executed on a background thread
|
||||
*/
|
||||
private void beforeShowFeedInformation(Feed feed) {
|
||||
// remove HTML tags from descriptions
|
||||
final HtmlToPlainText formatter = new HtmlToPlainText();
|
||||
if(Feed.TYPE_ATOM1.equals(feed.getType()) && feed.getDescription() != null) {
|
||||
// remove HTML tags from descriptions
|
||||
Log.d(TAG, "Removing HTML from feed description");
|
||||
Document feedDescription = Jsoup.parse(feed.getDescription());
|
||||
feed.setDescription(StringUtils.trim(formatter.getPlainText(feedDescription)));
|
||||
}
|
||||
Log.d(TAG, "Removing HTML from shownotes");
|
||||
if (feed.getItems() != null) {
|
||||
HtmlToPlainText formatter = new HtmlToPlainText();
|
||||
for (FeedItem item : feed.getItems()) {
|
||||
if (item.getDescription() != null) {
|
||||
Document description = Jsoup.parse(item.getDescription());
|
||||
item.setDescription(StringUtils.trim(formatter.getPlainText(description)));
|
||||
Document itemDescription = Jsoup.parse(item.getDescription());
|
||||
item.setDescription(StringUtils.trim(formatter.getPlainText(itemDescription)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -514,9 +519,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
|||
builder.setMessage(R.string.error_msg_prefix);
|
||||
}
|
||||
builder.setNeutralButton(android.R.string.ok,
|
||||
(dialog, which) -> {
|
||||
dialog.cancel();
|
||||
}
|
||||
(dialog, which) -> dialog.cancel()
|
||||
);
|
||||
builder.setOnCancelListener(dialog -> {
|
||||
setResult(RESULT_ERROR);
|
||||
|
@ -585,7 +588,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|
|||
|
||||
private String feedUrl;
|
||||
|
||||
public FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) {
|
||||
FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) {
|
||||
super(context, titleRes, true, false, null, null);
|
||||
this.feedUrl = feedUrl;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
|
||||
/**
|
||||
|
@ -23,10 +23,8 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
|
|||
* which feeds he wants to import.
|
||||
*/
|
||||
public class OpmlFeedChooserActivity extends AppCompatActivity {
|
||||
private static final String TAG = "OpmlFeedChooserActivity";
|
||||
|
||||
public static final String EXTRA_SELECTED_ITEMS = "de.danoeh.antennapod.selectedItems";
|
||||
|
||||
private static final String TAG = "OpmlFeedChooserActivity";
|
||||
private Button butConfirm;
|
||||
private Button butCancel;
|
||||
private ListView feedlist;
|
||||
|
|
|
@ -3,6 +3,7 @@ package de.danoeh.antennapod.activity;
|
|||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
|
@ -20,7 +21,7 @@ import java.util.ArrayList;
|
|||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.asynctask.OpmlFeedQueuer;
|
||||
import de.danoeh.antennapod.asynctask.OpmlImportWorker;
|
||||
import de.danoeh.antennapod.core.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.util.LangUtils;
|
||||
|
||||
/**
|
||||
|
@ -29,9 +30,8 @@ import de.danoeh.antennapod.core.util.LangUtils;
|
|||
public class OpmlImportBaseActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "OpmlImportBaseActivity";
|
||||
private OpmlImportWorker importWorker;
|
||||
|
||||
private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 5;
|
||||
private OpmlImportWorker importWorker;
|
||||
@Nullable private Uri uri;
|
||||
|
||||
/**
|
||||
|
@ -77,7 +77,8 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
|
|||
return;
|
||||
}
|
||||
this.uri = uri;
|
||||
if(uri.toString().contains(Environment.getExternalStorageDirectory().toString())) {
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
|
||||
uri.toString().contains(Environment.getExternalStorageDirectory().toString())) {
|
||||
int permission = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||
if (permission != PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermission();
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
|
||||
/** Lets the user start the OPML-import process. */
|
||||
/**
|
||||
* Lets the user start the OPML-import process.
|
||||
*/
|
||||
public class OpmlImportFromIntentActivity extends OpmlImportBaseActivity {
|
||||
|
||||
private static final String TAG = "OpmlImportFromIntentAct";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
Uri uri = getIntent().getData();
|
||||
if(uri.toString().startsWith("/")) {
|
||||
if (uri != null && uri.toString().startsWith("/")) {
|
||||
uri = Uri.parse("file://" + uri.toString());
|
||||
} else {
|
||||
uri = Uri.parse(getIntent().getStringExtra(Intent.EXTRA_TEXT));
|
||||
}
|
||||
importUri(uri);
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ public class OpmlImportFromPathActivity extends OpmlImportBaseActivity {
|
|||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (resultCode == RESULT_OK && requestCode == CHOOSE_OPML_FILE) {
|
||||
Uri uri = data.getData();
|
||||
if(uri.toString().startsWith("/")) {
|
||||
if(uri != null && uri.toString().startsWith("/")) {
|
||||
uri = Uri.parse("file://" + uri.toString());
|
||||
}
|
||||
importUri(uri);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import de.danoeh.antennapod.core.opml.OpmlElement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlElement;
|
||||
|
||||
/**
|
||||
* Hold infos gathered by Ompl-Import
|
||||
* <p/>
|
||||
|
|
|
@ -26,11 +26,9 @@ import de.danoeh.antennapod.preferences.PreferenceController;
|
|||
*/
|
||||
public class PreferenceActivity extends AppCompatActivity {
|
||||
|
||||
private static WeakReference<PreferenceActivity> instance;
|
||||
private PreferenceController preferenceController;
|
||||
private MainFragment prefFragment;
|
||||
private static WeakReference<PreferenceActivity> instance;
|
||||
|
||||
|
||||
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@Override
|
||||
|
@ -103,6 +101,7 @@ public class PreferenceActivity extends AppCompatActivity {
|
|||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
PreferenceActivity activity = instance.get();
|
||||
if(activity != null && activity.preferenceController != null) {
|
||||
|
@ -118,5 +117,23 @@ public class PreferenceActivity extends AppCompatActivity {
|
|||
activity.preferenceController.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
PreferenceActivity activity = instance.get();
|
||||
if(activity != null && activity.preferenceController != null) {
|
||||
activity.preferenceController.onPause();
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
PreferenceActivity activity = instance.get();
|
||||
if(activity != null && activity.preferenceController != null) {
|
||||
activity.preferenceController.onStop();
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,6 @@ import de.danoeh.antennapod.preferences.PreferenceController;
|
|||
*/
|
||||
public class PreferenceActivityGingerbread extends android.preference.PreferenceActivity {
|
||||
private static final String TAG = "PreferenceActivity";
|
||||
|
||||
private PreferenceController preferenceController;
|
||||
|
||||
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -34,6 +31,7 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
|
|||
return PreferenceActivityGingerbread.this;
|
||||
}
|
||||
};
|
||||
private PreferenceController preferenceController;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -54,6 +52,18 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
|
|||
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);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
/**
|
||||
* Creator: vbarad
|
||||
* Date: 2016-12-03
|
||||
* Project: AntennaPod
|
||||
*/
|
||||
|
||||
public class SplashActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -1,14 +1,18 @@
|
|||
package de.danoeh.antennapod.activity;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
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.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
|
@ -28,12 +32,16 @@ public class StatisticsActivity extends AppCompatActivity
|
|||
implements AdapterView.OnItemClickListener {
|
||||
|
||||
private static final String TAG = StatisticsActivity.class.getSimpleName();
|
||||
private static final String PREF_NAME = "StatisticsActivityPrefs";
|
||||
private static final String PREF_COUNT_ALL = "countAll";
|
||||
|
||||
private Subscription subscription;
|
||||
private TextView totalTimeTextView;
|
||||
private ListView feedStatisticsList;
|
||||
private ProgressBar progressBar;
|
||||
private StatisticsListAdapter listAdapter;
|
||||
private boolean countAll = false;
|
||||
private SharedPreferences prefs;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -42,10 +50,14 @@ public class StatisticsActivity extends AppCompatActivity
|
|||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
setContentView(R.layout.statistics_activity);
|
||||
|
||||
prefs = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
|
||||
countAll = prefs.getBoolean(PREF_COUNT_ALL, false);
|
||||
|
||||
totalTimeTextView = (TextView) findViewById(R.id.total_time);
|
||||
feedStatisticsList = (ListView) findViewById(R.id.statistics_list);
|
||||
progressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||
listAdapter = new StatisticsListAdapter(this);
|
||||
listAdapter.setCountAll(countAll);
|
||||
feedStatisticsList.setAdapter(listAdapter);
|
||||
feedStatisticsList.setOnItemClickListener(this);
|
||||
}
|
||||
|
@ -53,10 +65,15 @@ public class StatisticsActivity extends AppCompatActivity
|
|||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
totalTimeTextView.setVisibility(View.GONE);
|
||||
feedStatisticsList.setVisibility(View.GONE);
|
||||
loadStats();
|
||||
refreshStatistics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.statistics, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,30 +81,60 @@ public class StatisticsActivity extends AppCompatActivity
|
|||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.statistics_mode) {
|
||||
selectStatisticsMode();
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadStats() {
|
||||
if(subscription != null) {
|
||||
private void selectStatisticsMode() {
|
||||
View contentView = View.inflate(this, R.layout.statistics_mode_select_dialog, null);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setView(contentView);
|
||||
builder.setTitle(R.string.statistics_mode);
|
||||
|
||||
if (countAll) {
|
||||
((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).setChecked(true);
|
||||
} else {
|
||||
((RadioButton) contentView.findViewById(R.id.statistics_mode_normal)).setChecked(true);
|
||||
}
|
||||
|
||||
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
countAll = ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).isChecked();
|
||||
listAdapter.setCountAll(countAll);
|
||||
prefs.edit().putBoolean(PREF_COUNT_ALL, countAll).apply();
|
||||
refreshStatistics();
|
||||
});
|
||||
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void refreshStatistics() {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
totalTimeTextView.setVisibility(View.GONE);
|
||||
feedStatisticsList.setVisibility(View.GONE);
|
||||
loadStatistics();
|
||||
}
|
||||
|
||||
private void loadStatistics() {
|
||||
if (subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
subscription = Observable.fromCallable(() -> DBReader.getStatistics())
|
||||
subscription = Observable.fromCallable(() -> DBReader.getStatistics(countAll))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
if (result != null) {
|
||||
totalTimeTextView.setText(Converter
|
||||
.shortLocalizedDuration(this, result.totalTime));
|
||||
.shortLocalizedDuration(this, countAll ? result.totalTimeCountAll : result.totalTime));
|
||||
listAdapter.update(result.feedTime);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
totalTimeTextView.setVisibility(View.VISIBLE);
|
||||
feedStatisticsList.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -97,9 +144,10 @@ public class StatisticsActivity extends AppCompatActivity
|
|||
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
|
||||
dialog.setTitle(stats.feed.getTitle());
|
||||
dialog.setMessage(getString(R.string.statistics_details_dialog,
|
||||
stats.episodesStarted,
|
||||
countAll ? stats.episodesStartedIncludingMarked : stats.episodesStarted,
|
||||
stats.episodes,
|
||||
Converter.shortLocalizedDuration(this, stats.timePlayed),
|
||||
Converter.shortLocalizedDuration(this, countAll ?
|
||||
stats.timePlayedCountAll : stats.timePlayed),
|
||||
Converter.shortLocalizedDuration(this, stats.time)));
|
||||
dialog.setPositiveButton(android.R.string.ok, null);
|
||||
dialog.show();
|
||||
|
|
|
@ -55,7 +55,7 @@ public class StorageErrorActivity extends AppCompatActivity {
|
|||
openDirectoryChooser();
|
||||
}
|
||||
});
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
int readPermission = ActivityCompat.checkSelfPermission(this,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||
int writePermission = ActivityCompat.checkSelfPermission(this,
|
||||
|
|
|
@ -6,11 +6,13 @@ import android.content.res.Configuration;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
|
@ -40,7 +42,7 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService;
|
|||
* Step 2: Choose device from a list of available devices or create a new one
|
||||
* Step 3: Choose from a list of actions
|
||||
*/
|
||||
public class GpodnetAuthenticationActivity extends ActionBarActivity {
|
||||
public class GpodnetAuthenticationActivity extends AppCompatActivity {
|
||||
private static final String TAG = "GpodnetAuthActivity";
|
||||
|
||||
private static final String CURRENT_STEP = "current_step";
|
||||
|
@ -113,6 +115,9 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
|
|||
final TextView txtvError = (TextView) view.findViewById(R.id.txtvError);
|
||||
final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progBarLogin);
|
||||
|
||||
password.setOnEditorActionListener((v, actionID, event) ->
|
||||
actionID == EditorInfo.IME_ACTION_GO && login.performClick());
|
||||
|
||||
login.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -131,6 +136,11 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
|
|||
login.setEnabled(false);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
txtvError.setVisibility(View.GONE);
|
||||
// hide the keyboard
|
||||
InputMethodManager inputManager = (InputMethodManager)
|
||||
getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
inputManager.hideSoftInputFromWindow(login.getWindowToken(),
|
||||
InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package de.danoeh.antennapod.adapter;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
|
||||
public interface ActionButtonCallback {
|
||||
/** Is called when the action button of a list item has been pressed. */
|
||||
void onActionButtonPressed(FeedItem item);
|
||||
void onActionButtonPressed(FeedItem item, LongList queueIds);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class ActionButtonUtils {
|
|||
* Sets the displayed bitmap and content description of the given
|
||||
* action button so that it matches the state of the FeedItem.
|
||||
*/
|
||||
@SuppressWarnings("ResourceType")
|
||||
public void configureActionButton(ImageButton butSecondary, FeedItem item, boolean isInQueue) {
|
||||
Validate.isTrue(butSecondary != null && item != null, "butSecondary or item was null");
|
||||
|
||||
|
@ -57,8 +58,7 @@ public class ActionButtonUtils {
|
|||
if (isDownloadingMedia) {
|
||||
// item is being downloaded
|
||||
butSecondary.setVisibility(View.VISIBLE);
|
||||
butSecondary.setImageDrawable(drawables
|
||||
.getDrawable(1));
|
||||
butSecondary.setImageDrawable(drawables.getDrawable(1));
|
||||
butSecondary.setContentDescription(context.getString(labels[1]));
|
||||
} else {
|
||||
// item is not downloaded and not being downloaded
|
||||
|
|
|
@ -15,7 +15,7 @@ import de.danoeh.antennapod.core.util.NetworkUtils;
|
|||
/**
|
||||
* Utility methods for adapters
|
||||
*/
|
||||
public class AdapterUtils {
|
||||
class AdapterUtils {
|
||||
|
||||
private static final String TAG = AdapterUtils.class.getSimpleName();
|
||||
|
||||
|
@ -26,7 +26,7 @@ public class AdapterUtils {
|
|||
/**
|
||||
* Updates the contents of the TextView that shows the current playback position and the ProgressBar.
|
||||
*/
|
||||
public static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) {
|
||||
static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) {
|
||||
FeedMedia media = item.getMedia();
|
||||
episodeProgress.setVisibility(View.GONE);
|
||||
if (media == null) {
|
||||
|
@ -47,7 +47,6 @@ public class AdapterUtils {
|
|||
- media.getPosition()));
|
||||
}
|
||||
} else if (!media.isDownloaded()) {
|
||||
Log.d(TAG, "size: " + media.getSize());
|
||||
if (media.getSize() > 0) {
|
||||
txtvPos.setText(Converter.byteToString(media.getSize()));
|
||||
} else if(NetworkUtils.isDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
|
||||
|
|
|
@ -200,11 +200,11 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
holder.butSecondary.setOnClickListener(secondaryActionListener);
|
||||
|
||||
Glide.with(mainActivityRef.get())
|
||||
.load(item.getImageUri())
|
||||
.load(item.getImageLocation())
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(new CoverTarget(item.getFeed().getImageUri(), holder.placeholder, holder.cover, mainActivityRef.get()));
|
||||
.into(new CoverTarget(item.getFeed().getImageLocation(), holder.placeholder, holder.cover, mainActivityRef.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -232,7 +232,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
FeedItem item = (FeedItem) v.getTag();
|
||||
actionButtonCallback.onActionButtonPressed(item);
|
||||
actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -319,6 +319,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
|
||||
boolean isInQueue(FeedItem item);
|
||||
|
||||
LongList getQueueIds();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -60,6 +60,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
|
|||
defaultTextColor = holder.title.getTextColors().getDefaultColor();
|
||||
holder.start = (TextView) convertView.findViewById(R.id.txtvStart);
|
||||
holder.link = (TextView) convertView.findViewById(R.id.txtvLink);
|
||||
holder.duration = (TextView) convertView.findViewById(R.id.txtvDuration);
|
||||
holder.butPlayChapter = (ImageButton) convertView.findViewById(R.id.butPlayChapter);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
|
@ -70,6 +71,16 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
|
|||
holder.title.setText(sc.getTitle());
|
||||
holder.start.setText(Converter.getDurationStringLong((int) sc
|
||||
.getStart()));
|
||||
|
||||
long duration;
|
||||
if (position + 1 < media.getChapters().size()) {
|
||||
duration = media.getChapters().get(position + 1).getStart() - sc.getStart();
|
||||
} else {
|
||||
duration = media.getDuration() - sc.getStart();
|
||||
}
|
||||
holder.duration.setText(getContext().getString(R.string.chapter_duration,
|
||||
Converter.getDurationStringLong((int) duration)));
|
||||
|
||||
if (sc.getLink() != null) {
|
||||
holder.link.setVisibility(View.VISIBLE);
|
||||
holder.link.setText(sc.getLink());
|
||||
|
@ -155,6 +166,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
|
|||
TextView title;
|
||||
TextView start;
|
||||
TextView link;
|
||||
TextView duration;
|
||||
ImageButton butPlayChapter;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@ import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
|||
|
||||
class CoverTarget extends GlideDrawableImageViewTarget {
|
||||
|
||||
private final WeakReference<Uri> fallback;
|
||||
private final WeakReference<String> fallback;
|
||||
private final WeakReference<TextView> placeholder;
|
||||
private final WeakReference<ImageView> cover;
|
||||
private final WeakReference<MainActivity> mainActivity;
|
||||
|
||||
public CoverTarget(Uri fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) {
|
||||
public CoverTarget(String fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) {
|
||||
super(imgvCover);
|
||||
fallback = new WeakReference<>(fallbackUri);
|
||||
placeholder = new WeakReference<>(txtvPlaceholder);
|
||||
|
@ -33,7 +33,7 @@ class CoverTarget extends GlideDrawableImageViewTarget {
|
|||
|
||||
@Override
|
||||
public void onLoadFailed(Exception e, Drawable errorDrawable) {
|
||||
Uri fallbackUri = fallback.get();
|
||||
String fallbackUri = fallback.get();
|
||||
TextView txtvPlaceholder = placeholder.get();
|
||||
ImageView imgvCover = cover.get();
|
||||
if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
|
||||
|
@ -48,7 +48,7 @@ class CoverTarget extends GlideDrawableImageViewTarget {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) {
|
||||
public void onResourceReady(GlideDrawable drawable, GlideAnimation<? super GlideDrawable> anim) {
|
||||
super.onResourceReady(drawable, anim);
|
||||
TextView txtvPlaceholder = placeholder.get();
|
||||
if (txtvPlaceholder != null) {
|
||||
|
|
|
@ -51,13 +51,12 @@ public class DefaultActionButtonCallback implements ActionButtonCallback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onActionButtonPressed(final FeedItem item) {
|
||||
public void onActionButtonPressed(final FeedItem item, final LongList queueIds) {
|
||||
|
||||
if (item.hasMedia()) {
|
||||
final FeedMedia media = item.getMedia();
|
||||
boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
|
||||
if (!isDownloading && !media.isDownloaded()) {
|
||||
LongList queueIds = DBReader.getQueueIDList();
|
||||
if (NetworkUtils.isDownloadAllowed() || userAllowedMobileDownloads()) {
|
||||
try {
|
||||
DBTasks.downloadFeedItems(context, item);
|
||||
|
|
|
@ -12,6 +12,7 @@ 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;
|
||||
|
@ -77,7 +78,7 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
|
|||
}
|
||||
|
||||
Glide.with(context)
|
||||
.load(item.getImageUri())
|
||||
.load(item.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
|
@ -85,6 +86,12 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
|
|||
.dontAnimate()
|
||||
.into(holder.imageView);
|
||||
|
||||
if(item.isPlayed()) {
|
||||
ViewHelper.setAlpha(convertView, 0.5f);
|
||||
} else {
|
||||
ViewHelper.setAlpha(convertView, 1.0f);
|
||||
}
|
||||
|
||||
holder.title.setText(item.getTitle());
|
||||
holder.txtvSize.setText(Converter.byteToString(item.getMedia().getSize()));
|
||||
holder.queueStatus.setVisibility(item.isTagged(FeedItem.TAG_QUEUE) ? View.VISIBLE : View.GONE);
|
||||
|
|
|
@ -26,6 +26,7 @@ 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;
|
||||
import de.danoeh.antennapod.core.util.ThemeUtils;
|
||||
|
||||
/**
|
||||
|
@ -86,6 +87,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("ResourceType")
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
Holder holder;
|
||||
final FeedItem item = getItem(position);
|
||||
|
@ -219,7 +221,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
FeedItem item = (FeedItem) v.getTag();
|
||||
callback.onActionButtonPressed(item);
|
||||
callback.onActionButtonPressed(item, itemAccess.getQueueIds());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -243,6 +245,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
|
|||
|
||||
FeedItem getItem(int position);
|
||||
|
||||
LongList getQueueIds();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package de.danoeh.antennapod.adapter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.TypedArray;
|
||||
|
@ -21,6 +22,7 @@ import com.joanzapata.iconify.widget.IconTextView;
|
|||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -45,6 +47,7 @@ import de.danoeh.antennapod.fragment.SubscriptionFragment;
|
|||
*/
|
||||
public class NavListAdapter extends BaseAdapter
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
public static final int VIEW_TYPE_COUNT = 3;
|
||||
public static final int VIEW_TYPE_NAV = 0;
|
||||
public static final int VIEW_TYPE_SECTION_DIVIDER = 1;
|
||||
|
@ -60,12 +63,12 @@ public class NavListAdapter extends BaseAdapter
|
|||
private static String[] titles;
|
||||
|
||||
private ItemAccess itemAccess;
|
||||
private Context context;
|
||||
private WeakReference<Activity> activity;
|
||||
private boolean showSubscriptionList = true;
|
||||
|
||||
public NavListAdapter(ItemAccess itemAccess, Context context) {
|
||||
public NavListAdapter(ItemAccess itemAccess, Activity context) {
|
||||
this.itemAccess = itemAccess;
|
||||
this.context = context;
|
||||
this.activity = new WeakReference<>(context);
|
||||
|
||||
titles = context.getResources().getStringArray(R.array.nav_drawer_titles);
|
||||
loadItems();
|
||||
|
@ -108,6 +111,10 @@ public class NavListAdapter extends BaseAdapter
|
|||
}
|
||||
|
||||
private Drawable getDrawable(String tag) {
|
||||
Activity context = activity.get();
|
||||
if(context == null) {
|
||||
return null;
|
||||
}
|
||||
int icon;
|
||||
switch (tag) {
|
||||
case QueueFragment.TAG:
|
||||
|
@ -218,6 +225,10 @@ public class NavListAdapter extends BaseAdapter
|
|||
}
|
||||
|
||||
private View getNavView(String title, int position, View convertView, ViewGroup parent) {
|
||||
Activity context = activity.get();
|
||||
if(context == null) {
|
||||
return null;
|
||||
}
|
||||
NavHolder holder;
|
||||
if (convertView == null) {
|
||||
holder = new NavHolder();
|
||||
|
@ -236,30 +247,28 @@ public class NavListAdapter extends BaseAdapter
|
|||
|
||||
holder.title.setText(title);
|
||||
|
||||
// reset for re-use
|
||||
holder.count.setVisibility(View.GONE);
|
||||
holder.count.setOnClickListener(null);
|
||||
|
||||
String tag = tags.get(position);
|
||||
if (tag.equals(QueueFragment.TAG)) {
|
||||
int queueSize = itemAccess.getQueueSize();
|
||||
if (queueSize > 0) {
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
holder.count.setText(String.valueOf(queueSize));
|
||||
} else {
|
||||
holder.count.setVisibility(View.GONE);
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if (tag.equals(EpisodesFragment.TAG)) {
|
||||
int unreadItems = itemAccess.getNumberOfNewItems();
|
||||
if (unreadItems > 0) {
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
holder.count.setText(String.valueOf(unreadItems));
|
||||
} else {
|
||||
holder.count.setVisibility(View.GONE);
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if (tag.equals(SubscriptionFragment.TAG)) {
|
||||
int sum = itemAccess.getFeedCounterSum();
|
||||
if (sum > 0) {
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
holder.count.setText(String.valueOf(sum));
|
||||
} else {
|
||||
holder.count.setVisibility(View.GONE);
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if(tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) {
|
||||
int epCacheSize = UserPreferences.getEpisodeCacheSize();
|
||||
|
@ -278,11 +287,7 @@ public class NavListAdapter extends BaseAdapter
|
|||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {})
|
||||
.show()
|
||||
);
|
||||
} else {
|
||||
holder.count.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
holder.count.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
holder.image.setImageDrawable(getDrawable(tags.get(position)));
|
||||
|
@ -291,6 +296,10 @@ public class NavListAdapter extends BaseAdapter
|
|||
}
|
||||
|
||||
private View getSectionDividerView(View convertView, ViewGroup parent) {
|
||||
Activity context = activity.get();
|
||||
if(context == null) {
|
||||
return null;
|
||||
}
|
||||
LayoutInflater inflater = (LayoutInflater) context
|
||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
|
@ -303,6 +312,10 @@ public class NavListAdapter extends BaseAdapter
|
|||
}
|
||||
|
||||
private View getFeedView(int position, View convertView, ViewGroup parent) {
|
||||
Activity context = activity.get();
|
||||
if(context == null) {
|
||||
return null;
|
||||
}
|
||||
int feedPos = position - getSubscriptionOffset();
|
||||
Feed feed = itemAccess.getItem(feedPos);
|
||||
|
||||
|
@ -324,7 +337,7 @@ public class NavListAdapter extends BaseAdapter
|
|||
}
|
||||
|
||||
Glide.with(context)
|
||||
.load(feed.getImageUri())
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
|
|
|
@ -296,11 +296,11 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
|||
butSecondary.setOnClickListener(secondaryActionListener);
|
||||
|
||||
Glide.with(mainActivity.get())
|
||||
.load(item.getImageUri())
|
||||
.load(item.getImageLocation())
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(new CoverTarget(item.getFeed().getImageUri(), placeholder, cover, mainActivity.get()));
|
||||
.into(new CoverTarget(item.getFeed().getImageLocation(), placeholder, cover, mainActivity.get()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
FeedItem item = (FeedItem) v.getTag();
|
||||
actionButtonCallback.onActionButtonPressed(item);
|
||||
actionButtonCallback.onActionButtonPressed(item, itemAccess.getQueueIds());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ 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;
|
||||
|
@ -80,7 +81,7 @@ public class SearchlistAdapter extends BaseAdapter {
|
|||
holder.subtitle.setVisibility(View.GONE);
|
||||
|
||||
Glide.with(context)
|
||||
.load(feed.getImageUri())
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
|
@ -96,8 +97,10 @@ public class SearchlistAdapter extends BaseAdapter {
|
|||
holder.subtitle.setText(result.getSubtitle());
|
||||
}
|
||||
|
||||
ViewHelper.setAlpha(convertView, item.isPlayed() ? 0.5f : 1.0f);
|
||||
|
||||
Glide.with(context)
|
||||
.load(item.getFeed().getImageUri())
|
||||
.load(item.getFeed().getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
|
|
|
@ -9,11 +9,9 @@ import android.widget.ImageView;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.joanzapata.iconify.widget.IconTextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
|
@ -27,11 +25,15 @@ import de.danoeh.antennapod.core.util.Converter;
|
|||
public class StatisticsListAdapter extends BaseAdapter {
|
||||
private Context context;
|
||||
List<DBReader.StatisticsItem> feedTime = new ArrayList<>();
|
||||
private boolean countAll = true;
|
||||
|
||||
public StatisticsListAdapter(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setCountAll(boolean countAll) {
|
||||
this.countAll = countAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
|
@ -69,7 +71,7 @@ public class StatisticsListAdapter extends BaseAdapter {
|
|||
}
|
||||
|
||||
Glide.with(context)
|
||||
.load(feed.getImageUri())
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
|
@ -79,7 +81,8 @@ public class StatisticsListAdapter extends BaseAdapter {
|
|||
|
||||
holder.title.setText(feed.getTitle());
|
||||
holder.time.setText(Converter.shortLocalizedDuration(context,
|
||||
feedTime.get(position).timePlayed));
|
||||
countAll ? feedTime.get(position).timePlayedCountAll
|
||||
: feedTime.get(position).timePlayed));
|
||||
return convertView;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package de.danoeh.antennapod.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -32,8 +30,8 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
|
|||
/** placeholder object that indicates item should be added */
|
||||
public static final Object ADD_ITEM_OBJ = new Object();
|
||||
|
||||
/** the position in the view that holds the add item */
|
||||
private static final int ADD_POSITION = 0;
|
||||
/** the position in the view that holds the add item; 0 is the first, -1 is the last position */
|
||||
private static final int ADD_POSITION = -1;
|
||||
private static final String TAG = "SubscriptionsAdapter";
|
||||
|
||||
private final WeakReference<MainActivity> mainActivityRef;
|
||||
|
@ -44,8 +42,16 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
|
|||
this.itemAccess = itemAccess;
|
||||
}
|
||||
|
||||
private int getAddTilePosition() {
|
||||
if(ADD_POSITION < 0) {
|
||||
return ADD_POSITION + getCount();
|
||||
}
|
||||
return ADD_POSITION;
|
||||
}
|
||||
|
||||
private int getAdjustedPosition(int origPosition) {
|
||||
return origPosition - 1;
|
||||
assert(origPosition != getAddTilePosition());
|
||||
return origPosition < getAddTilePosition() ? origPosition : origPosition - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,15 +61,20 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
|
|||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
if (position == ADD_POSITION) {
|
||||
if (position == getAddTilePosition()) {
|
||||
return ADD_ITEM_OBJ;
|
||||
}
|
||||
return itemAccess.getItem(getAdjustedPosition(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
if (position == ADD_POSITION) {
|
||||
if (position == getAddTilePosition()) {
|
||||
return 0;
|
||||
}
|
||||
return itemAccess.getItem(getAdjustedPosition(position)).getId();
|
||||
|
@ -89,13 +100,17 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
|
|||
holder = (Holder) convertView.getTag();
|
||||
}
|
||||
|
||||
if (position == ADD_POSITION) {
|
||||
if (position == getAddTilePosition()) {
|
||||
holder.feedTitle.setText("{md-add 500%}\n\n" + mainActivityRef.get().getString(R.string.add_feed_label));
|
||||
holder.feedTitle.setVisibility(View.VISIBLE);
|
||||
// prevent any accidental re-use of old values (not sure how that would happen...)
|
||||
holder.count.setPrimaryText("");
|
||||
// make it go away, we don't need it for add feed
|
||||
holder.count.setVisibility(View.INVISIBLE);
|
||||
|
||||
// when this holder is reused, we could else end up with a cover image
|
||||
Glide.clear(holder.imageView);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
|
@ -104,10 +119,15 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
|
|||
|
||||
holder.feedTitle.setText(feed.getTitle());
|
||||
holder.feedTitle.setVisibility(View.VISIBLE);
|
||||
holder.count.setPrimaryText(String.valueOf(itemAccess.getFeedCounter(feed.getId())));
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
int count = itemAccess.getFeedCounter(feed.getId());
|
||||
if(count > 0) {
|
||||
holder.count.setPrimaryText(String.valueOf(itemAccess.getFeedCounter(feed.getId())));
|
||||
holder.count.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.count.setVisibility(View.GONE);
|
||||
}
|
||||
Glide.with(mainActivityRef.get())
|
||||
.load(feed.getImageUri())
|
||||
.load(feed.getImageLocation())
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
|
@ -119,7 +139,7 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
|
|||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (position == ADD_POSITION) {
|
||||
if (position == getAddTilePosition()) {
|
||||
mainActivityRef.get().loadChildFragment(new AddFeedFragment());
|
||||
} else {
|
||||
Fragment fragment = ItemlistFragment.newInstance(getItemId(position));
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package de.danoeh.antennapod.adapter.itunes;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
@ -18,6 +20,7 @@ import java.util.List;
|
|||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.mfietz.fyydlin.SearchHit;
|
||||
|
||||
public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
||||
/**
|
||||
|
@ -42,8 +45,9 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
|||
this.context = context;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
//Current podcast
|
||||
Podcast podcast = data.get(position);
|
||||
|
||||
|
@ -66,7 +70,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
|||
|
||||
//Set the title
|
||||
viewHolder.titleView.setText(podcast.title);
|
||||
if(!podcast.feedUrl.contains("itunes.apple.com")) {
|
||||
if(podcast.feedUrl != null && !podcast.feedUrl.contains("itunes.apple.com")) {
|
||||
viewHolder.urlView.setText(podcast.feedUrl);
|
||||
viewHolder.urlView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
|
@ -86,35 +90,6 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
|||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder object for the GridView
|
||||
*/
|
||||
class PodcastViewHolder {
|
||||
|
||||
/**
|
||||
* ImageView holding the Podcast image
|
||||
*/
|
||||
public final ImageView coverView;
|
||||
|
||||
/**
|
||||
* TextView holding the Podcast title
|
||||
*/
|
||||
public final TextView titleView;
|
||||
|
||||
public final TextView urlView;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param view GridView cell
|
||||
*/
|
||||
PodcastViewHolder(View view){
|
||||
coverView = (ImageView) view.findViewById(R.id.imgvCover);
|
||||
titleView = (TextView) view.findViewById(R.id.txtvTitle);
|
||||
urlView = (TextView) view.findViewById(R.id.txtvUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an individual podcast on the iTunes Store.
|
||||
*/
|
||||
|
@ -128,14 +103,16 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
|||
/**
|
||||
* URL of the podcast image
|
||||
*/
|
||||
@Nullable
|
||||
public final String imageUrl;
|
||||
/**
|
||||
* URL of the podcast feed
|
||||
*/
|
||||
@Nullable
|
||||
public final String feedUrl;
|
||||
|
||||
|
||||
private Podcast(String title, String imageUrl, String feedUrl) {
|
||||
private Podcast(String title, @Nullable String imageUrl, @Nullable String feedUrl) {
|
||||
this.title = title;
|
||||
this.imageUrl = imageUrl;
|
||||
this.feedUrl = feedUrl;
|
||||
|
@ -148,12 +125,16 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
|||
* @throws JSONException
|
||||
*/
|
||||
public static Podcast fromSearch(JSONObject json) throws JSONException {
|
||||
String title = json.getString("collectionName");
|
||||
String imageUrl = json.getString("artworkUrl100");
|
||||
String feedUrl = json.getString("feedUrl");
|
||||
String title = json.optString("collectionName", "");
|
||||
String imageUrl = json.optString("artworkUrl100", null);
|
||||
String feedUrl = json.optString("feedUrl", null);
|
||||
return new Podcast(title, imageUrl, feedUrl);
|
||||
}
|
||||
|
||||
public static Podcast fromSearch(SearchHit searchHit) {
|
||||
return new Podcast(searchHit.getTitle(), searchHit.getImageUrl(), searchHit.getXmlUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Podcast instance from iTunes toplist entry
|
||||
*
|
||||
|
@ -177,4 +158,33 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder object for the GridView
|
||||
*/
|
||||
class PodcastViewHolder {
|
||||
|
||||
/**
|
||||
* ImageView holding the Podcast image
|
||||
*/
|
||||
final ImageView coverView;
|
||||
|
||||
/**
|
||||
* TextView holding the Podcast title
|
||||
*/
|
||||
final TextView titleView;
|
||||
|
||||
final TextView urlView;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param view GridView cell
|
||||
*/
|
||||
PodcastViewHolder(View view){
|
||||
coverView = (ImageView) view.findViewById(R.id.imgvCover);
|
||||
titleView = (TextView) view.findViewById(R.id.txtvTitle);
|
||||
urlView = (TextView) view.findViewById(R.id.txtvUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package de.danoeh.antennapod.asynctask;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import de.danoeh.antennapod.core.export.ExportWriter;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.util.LangUtils;
|
||||
import rx.Observable;
|
||||
|
||||
/**
|
||||
* Writes an OPML file into the export directory in the background.
|
||||
*/
|
||||
public class ExportWorker {
|
||||
|
||||
private static final String EXPORT_DIR = "export/";
|
||||
private static final String TAG = "ExportWorker";
|
||||
private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds";
|
||||
|
||||
private ExportWriter exportWriter;
|
||||
private 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) {
|
||||
this.exportWriter = exportWriter;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public Observable<File> exportObservable() {
|
||||
if (output.exists()) {
|
||||
Log.w(TAG, "Overwriting previously exported file.");
|
||||
output.delete();
|
||||
}
|
||||
return Observable.create(subscriber -> {
|
||||
OutputStreamWriter writer = null;
|
||||
try {
|
||||
writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
|
||||
exportWriter.writeDocument(DBReader.getFeedList(), writer);
|
||||
subscriber.onNext(output);
|
||||
} catch (IOException e) {
|
||||
subscriber.onError(e);
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
subscriber.onError(e);
|
||||
}
|
||||
}
|
||||
subscriber.onCompleted();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
package de.danoeh.antennapod.asynctask;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.opml.OpmlWriter;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.util.LangUtils;
|
||||
|
||||
/**
|
||||
* Writes an OPML file into the export directory in the background.
|
||||
*/
|
||||
public class OpmlExportWorker extends AsyncTask<Void, Void, Void> {
|
||||
private static final String TAG = "OpmlExportWorker";
|
||||
private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds.opml";
|
||||
public static final String EXPORT_DIR = "export/";
|
||||
|
||||
private Context context;
|
||||
private File output;
|
||||
|
||||
private ProgressDialog progDialog;
|
||||
private Exception exception;
|
||||
|
||||
public OpmlExportWorker(Context context, File output) {
|
||||
this.context = context;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public OpmlExportWorker(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
OpmlWriter opmlWriter = new OpmlWriter();
|
||||
if (output == null) {
|
||||
output = new File(
|
||||
UserPreferences.getDataFolder(EXPORT_DIR),
|
||||
DEFAULT_OUTPUT_NAME);
|
||||
if (output.exists()) {
|
||||
Log.w(TAG, "Overwriting previously exported file.");
|
||||
output.delete();
|
||||
}
|
||||
}
|
||||
OutputStreamWriter writer = null;
|
||||
try {
|
||||
writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8);
|
||||
opmlWriter.writeDocument(DBReader.getFeedList(), writer);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
exception = e;
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException ioe) {
|
||||
exception = ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
progDialog.dismiss();
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(context)
|
||||
.setNeutralButton(android.R.string.ok,
|
||||
(dialog, which) -> dialog.dismiss());
|
||||
if (exception != null) {
|
||||
alert.setTitle(R.string.export_error_label);
|
||||
alert.setMessage(exception.getMessage());
|
||||
} else {
|
||||
alert.setTitle(R.string.opml_export_success_title);
|
||||
alert.setMessage(context
|
||||
.getString(R.string.opml_export_success_sum)
|
||||
+ output.toString())
|
||||
.setPositiveButton(R.string.send_label, (dialog, which) -> {
|
||||
Uri outputUri = Uri.fromFile(output);
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT,
|
||||
context.getResources().getText(R.string.opml_export_label));
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri);
|
||||
sendIntent.setType("text/plain");
|
||||
context.startActivity(Intent.createChooser(sendIntent,
|
||||
context.getResources().getText(R.string.send_label)));
|
||||
});
|
||||
}
|
||||
alert.create().show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
progDialog = new ProgressDialog(context);
|
||||
progDialog.setMessage(context.getString(R.string.exporting_label));
|
||||
progDialog.setIndeterminate(true);
|
||||
progDialog.show();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -9,8 +9,8 @@ import java.util.Arrays;
|
|||
|
||||
import de.danoeh.antennapod.activity.OpmlImportHolder;
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ import java.io.Reader;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.opml.OpmlReader;
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlElement;
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlReader;
|
||||
|
||||
public class OpmlImportWorker extends
|
||||
AsyncTask<Void, Void, ArrayList<OpmlElement>> {
|
||||
|
@ -75,9 +75,7 @@ public class OpmlImportWorker extends
|
|||
alert.setTitle(R.string.error_label);
|
||||
alert.setMessage(context.getString(R.string.opml_reader_error)
|
||||
+ exception.getMessage());
|
||||
alert.setNeutralButton(android.R.string.ok, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
alert.setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
|
||||
alert.create().show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,5 +18,6 @@ public class ClientConfigurator {
|
|||
ClientConfig.playbackServiceCallbacks = new PlaybackServiceCallbacksImpl();
|
||||
ClientConfig.flattrCallbacks = new FlattrCallbacksImpl();
|
||||
ClientConfig.dbTasksCallbacks = new DBTasksCallbacksImpl();
|
||||
ClientConfig.castCallbacks = new CastCallbackImpl();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,6 +225,10 @@ public class EpisodesApplyActionFragment extends Fragment {
|
|||
checkQueued(false);
|
||||
resId = R.string.selected_not_queued_label;
|
||||
break;
|
||||
case R.id.check_has_media:
|
||||
checkWithMedia();
|
||||
resId = R.string.selected_has_media_label;
|
||||
break;
|
||||
case R.id.sort_title_a_z:
|
||||
sortByTitle(false);
|
||||
return true;
|
||||
|
@ -357,6 +361,17 @@ public class EpisodesApplyActionFragment extends Fragment {
|
|||
refreshCheckboxes();
|
||||
}
|
||||
|
||||
private void checkWithMedia() {
|
||||
for (FeedItem episode : episodes) {
|
||||
if(episode.hasMedia()) {
|
||||
checkedIds.add(episode.getId());
|
||||
} else {
|
||||
checkedIds.remove(episode.getId());
|
||||
}
|
||||
}
|
||||
refreshCheckboxes();
|
||||
}
|
||||
|
||||
private void refreshTitles() {
|
||||
titles.clear();
|
||||
for(FeedItem episode : episodes) {
|
||||
|
|
|
@ -35,9 +35,7 @@ public class GpodnetSetHostnameDialog {
|
|||
}
|
||||
dialog1.dismiss();
|
||||
})
|
||||
.setNegativeButton(R.string.cancel_label, (dialog1, which) -> {
|
||||
dialog1.cancel();
|
||||
})
|
||||
.setNegativeButton(R.string.cancel_label, (dialog1, which) -> dialog1.cancel())
|
||||
.setNeutralButton(R.string.pref_gpodnet_sethostname_use_default_host, (dialog1, which) -> {
|
||||
GpodnetPreferences.setHostname(GpodnetService.DEFAULT_BASE_HOST);
|
||||
dialog1.dismiss();
|
||||
|
|
|
@ -18,10 +18,6 @@ import android.widget.TextView;
|
|||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.afollestad.materialdialogs.internal.MDButton;
|
||||
import com.squareup.okhttp.Credentials;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
@ -33,6 +29,10 @@ import de.danoeh.antennapod.R;
|
|||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||
import de.danoeh.antennapod.core.service.download.ProxyConfig;
|
||||
import okhttp3.Credentials;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import rx.Observable;
|
||||
import rx.Subscriber;
|
||||
import rx.Subscription;
|
||||
|
@ -258,10 +258,11 @@ public class ProxyDialog {
|
|||
SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
|
||||
Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
|
||||
Proxy proxy = new Proxy(proxyType, address);
|
||||
OkHttpClient client = AntennapodHttpClient.newHttpClient();
|
||||
client.setConnectTimeout(10, TimeUnit.SECONDS);
|
||||
client.setProxy(proxy);
|
||||
client.interceptors().clear();
|
||||
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 -> {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package de.danoeh.antennapod.dialog;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.text.InputType;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
|
||||
public class RenameFeedDialog {
|
||||
|
||||
private final WeakReference<Activity> activityRef;
|
||||
private final Feed feed;
|
||||
|
||||
public RenameFeedDialog(Activity activity, Feed feed) {
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
this.feed = feed;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
Activity activity = activityRef.get();
|
||||
if(activity == null) {
|
||||
return;
|
||||
}
|
||||
new MaterialDialog.Builder(activity)
|
||||
.title(de.danoeh.antennapod.core.R.string.rename_feed_label)
|
||||
.inputType(InputType.TYPE_CLASS_TEXT)
|
||||
.input(feed.getTitle(), feed.getTitle(), true, (dialog, input) -> {
|
||||
feed.setCustomTitle(input.toString());
|
||||
DBWriter.setFeedCustomTitle(feed);
|
||||
dialog.dismiss();
|
||||
})
|
||||
.neutralText(de.danoeh.antennapod.core.R.string.reset)
|
||||
.onNeutral((dialog, which) -> dialog.getInputEditText().setText(feed.getFeedTitle()))
|
||||
.negativeText(de.danoeh.antennapod.core.R.string.cancel_label)
|
||||
.onNegative((dialog, which) -> dialog.dismiss())
|
||||
.autoDismiss(false)
|
||||
.show();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package de.danoeh.antennapod.dialog;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
|
@ -9,6 +9,7 @@ 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;
|
||||
|
@ -16,36 +17,27 @@ import android.widget.Toast;
|
|||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.event.MessageEvent;
|
||||
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
public abstract class SleepTimerDialog {
|
||||
|
||||
private static final String TAG = SleepTimerDialog.class.getSimpleName();
|
||||
|
||||
private static final int DEFAULT_SPINNER_POSITION = 1;
|
||||
|
||||
private Context context;
|
||||
private String PREF_NAME = "SleepTimerDialog";
|
||||
private String PREF_VALUE = "LastValue";
|
||||
private String PREF_TIME_UNIT = "LastTimeUnit";
|
||||
private String PREF_VIBRATE = "Vibrate";
|
||||
private String PREF_SHAKE_TO_RESET = "ShakeToReset";
|
||||
private SharedPreferences prefs;
|
||||
|
||||
private MaterialDialog dialog;
|
||||
private EditText etxtTime;
|
||||
private Spinner spTimeUnit;
|
||||
private CheckBox cbShakeToReset;
|
||||
private CheckBox cbVibrate;
|
||||
private CheckBox chAutoEnable;
|
||||
|
||||
|
||||
private TimeUnit[] units = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS };
|
||||
|
||||
public SleepTimerDialog(Context context) {
|
||||
protected SleepTimerDialog(Context context) {
|
||||
this.context = context;
|
||||
prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public MaterialDialog createNewDialog() {
|
||||
|
@ -58,7 +50,7 @@ public abstract class SleepTimerDialog {
|
|||
builder.onPositive((dialog, which) -> {
|
||||
try {
|
||||
savePreferences();
|
||||
long input = readTimeMillis();
|
||||
long input = SleepTimerPreferences.timerMillis();
|
||||
onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked());
|
||||
dialog.dismiss();
|
||||
} catch (NumberFormatException e) {
|
||||
|
@ -75,8 +67,9 @@ public abstract class SleepTimerDialog {
|
|||
spTimeUnit = (Spinner) view.findViewById(R.id.spTimeUnit);
|
||||
cbShakeToReset = (CheckBox) view.findViewById(R.id.cbShakeToReset);
|
||||
cbVibrate = (CheckBox) view.findViewById(R.id.cbVibrate);
|
||||
chAutoEnable = (CheckBox) view.findViewById(R.id.chAutoEnable);
|
||||
|
||||
etxtTime.setText(prefs.getString(PREF_VALUE, "15"));
|
||||
etxtTime.setText(SleepTimerPreferences.lastTimerValue());
|
||||
etxtTime.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
@ -104,12 +97,17 @@ public abstract class SleepTimerDialog {
|
|||
android.R.layout.simple_spinner_item, spinnerContent);
|
||||
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spTimeUnit.setAdapter(spinnerAdapter);
|
||||
int selection = prefs.getInt(PREF_TIME_UNIT, DEFAULT_SPINNER_POSITION);
|
||||
spTimeUnit.setSelection(selection);
|
||||
spTimeUnit.setSelection(SleepTimerPreferences.lastTimerTimeUnit());
|
||||
|
||||
cbShakeToReset.setChecked(prefs.getBoolean(PREF_SHAKE_TO_RESET, true));
|
||||
cbVibrate.setChecked(prefs.getBoolean(PREF_VIBRATE, true));
|
||||
cbShakeToReset.setChecked(SleepTimerPreferences.shakeToReset());
|
||||
cbVibrate.setChecked(SleepTimerPreferences.vibrate());
|
||||
chAutoEnable.setChecked(SleepTimerPreferences.autoEnable());
|
||||
|
||||
chAutoEnable.setOnCheckedChangeListener((compoundButton, isChecked) -> {
|
||||
SleepTimerPreferences.setAutoEnable(isChecked);
|
||||
int messageString = isChecked ? R.string.sleep_timer_enabled_label : R.string.sleep_timer_disabled_label;
|
||||
EventBus.getDefault().post(new MessageEvent(context.getString(messageString)));
|
||||
});
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
@ -125,19 +123,12 @@ public abstract class SleepTimerDialog {
|
|||
|
||||
public abstract void onTimerSet(long millis, boolean shakeToReset, boolean vibrate);
|
||||
|
||||
private long readTimeMillis() {
|
||||
TimeUnit selectedUnit = units[spTimeUnit.getSelectedItemPosition()];
|
||||
long value = Long.parseLong(etxtTime.getText().toString());
|
||||
return selectedUnit.toMillis(value);
|
||||
}
|
||||
|
||||
private void savePreferences() {
|
||||
prefs.edit()
|
||||
.putString(PREF_VALUE, etxtTime.getText().toString())
|
||||
.putInt(PREF_TIME_UNIT, spTimeUnit.getSelectedItemPosition())
|
||||
.putBoolean(PREF_SHAKE_TO_RESET, cbShakeToReset.isChecked())
|
||||
.putBoolean(PREF_VIBRATE, cbVibrate.isChecked())
|
||||
.apply();
|
||||
SleepTimerPreferences.setLastTimer(etxtTime.getText().toString(),
|
||||
spTimeUnit.getSelectedItemPosition());
|
||||
SleepTimerPreferences.setShakeToReset(cbShakeToReset.isChecked());
|
||||
SleepTimerPreferences.setVibrate(cbVibrate.isChecked());
|
||||
SleepTimerPreferences.setAutoEnable(chAutoEnable.isChecked());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -95,9 +95,7 @@ public class VariableSpeedDialog {
|
|||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.set_playback_speed_label);
|
||||
builder.setMultiChoiceItems(R.array.playback_speed_values,
|
||||
speedChecked, (dialog, which, isChecked) -> {
|
||||
speedChecked[which] = isChecked;
|
||||
});
|
||||
speedChecked, (dialog, which, isChecked) -> speedChecked[which] = isChecked);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
builder.setPositiveButton(android.R.string.ok,
|
||||
(dialog, which) -> {
|
||||
|
|
|
@ -39,10 +39,11 @@ public class AddFeedFragment extends Fragment {
|
|||
etxtFeedurl.setText(args.getString(ARG_FEED_URL));
|
||||
}
|
||||
|
||||
Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes);
|
||||
Button butBrowserGpoddernet = (Button) root.findViewById(R.id.butBrowseGpoddernet);
|
||||
Button butSearchFyyd = (Button) root.findViewById(R.id.butSearchFyyd);
|
||||
Button butOpmlImport = (Button) root.findViewById(R.id.butOpmlImport);
|
||||
Button butConfirm = (Button) root.findViewById(R.id.butConfirm);
|
||||
Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes);
|
||||
|
||||
final MainActivity activity = (MainActivity) getActivity();
|
||||
activity.getSupportActionBar().setTitle(R.string.add_feed_label);
|
||||
|
@ -51,6 +52,8 @@ public class AddFeedFragment extends Fragment {
|
|||
|
||||
butBrowserGpoddernet.setOnClickListener(v -> activity.loadChildFragment(new GpodnetMainFragment()));
|
||||
|
||||
butSearchFyyd.setOnClickListener(v -> activity.loadChildFragment(new FyydSearchFragment()));
|
||||
|
||||
butOpmlImport.setOnClickListener(v -> startActivity(new Intent(getActivity(),
|
||||
OpmlImportFromPathActivity.class)));
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ public class AllEpisodesFragment extends Fragment {
|
|||
private boolean viewsCreated = false;
|
||||
|
||||
private boolean isUpdatingFeeds;
|
||||
protected boolean isMenuInvalidationAllowed = false;
|
||||
|
||||
protected Subscription subscription;
|
||||
private LinearLayoutManager layoutManager;
|
||||
|
@ -180,7 +181,7 @@ public class AllEpisodesFragment extends Fragment {
|
|||
}
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
if (itemsLoaded) {
|
||||
inflater.inflate(R.menu.new_episodes, menu);
|
||||
inflater.inflate(R.menu.episodes, menu);
|
||||
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
|
@ -206,11 +207,13 @@ public class AllEpisodesFragment extends Fragment {
|
|||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
if (itemsLoaded) {
|
||||
MenuItem menuItem = menu.findItem(R.id.mark_all_read_item);
|
||||
if (menuItem != null) {
|
||||
menuItem.setVisible(episodes != null && !episodes.isEmpty());
|
||||
}
|
||||
MenuItem markAllRead = menu.findItem(R.id.mark_all_read_item);
|
||||
if (markAllRead != null) {
|
||||
markAllRead.setVisible(!showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty());
|
||||
}
|
||||
MenuItem markAllSeen = menu.findItem(R.id.mark_all_seen_item);
|
||||
if(markAllSeen != null) {
|
||||
markAllSeen.setVisible(showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,19 +228,32 @@ public class AllEpisodesFragment extends Fragment {
|
|||
}
|
||||
return true;
|
||||
case R.id.mark_all_read_item:
|
||||
ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(),
|
||||
ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(),
|
||||
R.string.mark_all_read_label,
|
||||
R.string.mark_all_read_confirmation_msg) {
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(
|
||||
DialogInterface dialog) {
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
DBWriter.markAllItemsRead();
|
||||
Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
conDialog.createNewDialog().show();
|
||||
markAllReadConfirmationDialog.createNewDialog().show();
|
||||
return true;
|
||||
case R.id.mark_all_seen_item:
|
||||
ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(),
|
||||
R.string.mark_all_seen_label,
|
||||
R.string.mark_all_seen_confirmation_msg) {
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
DBWriter.markNewItemsSeen();
|
||||
Toast.makeText(getActivity(), R.string.mark_all_seen_msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
markAllSeenConfirmationDialog.createNewDialog().show();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -378,6 +394,20 @@ public class AllEpisodesFragment extends Fragment {
|
|||
return item != null && item.isTagged(FeedItem.TAG_QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongList getQueueIds() {
|
||||
LongList queueIds = new LongList();
|
||||
if(episodes == null) {
|
||||
return queueIds;
|
||||
}
|
||||
for(FeedItem item : episodes) {
|
||||
if(item.isTagged(FeedItem.TAG_QUEUE)) {
|
||||
queueIds.add(item.getId());
|
||||
}
|
||||
}
|
||||
return queueIds;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public void onEventMainThread(FeedItemEvent event) {
|
||||
|
@ -401,7 +431,7 @@ public class AllEpisodesFragment extends Fragment {
|
|||
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
||||
DownloaderUpdate update = event.update;
|
||||
downloaderList = update.downloaders;
|
||||
if (isUpdatingFeeds != update.feedIds.length > 0) {
|
||||
if (isMenuInvalidationAllowed && isUpdatingFeeds != update.feedIds.length > 0) {
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
}
|
||||
if(listAdapter != null && update.mediaIds.length > 0) {
|
||||
|
@ -450,9 +480,7 @@ public class AllEpisodesFragment extends Fragment {
|
|||
onFragmentLoaded();
|
||||
}
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
protected List<FeedItem> loadData() {
|
||||
|
|
|
@ -69,16 +69,18 @@ public class ChaptersFragment extends ListFragment implements MediaplayerInfoCon
|
|||
|
||||
@Override
|
||||
public void onMediaChanged(Playable media) {
|
||||
if(this.media == media || adapter == null) {
|
||||
if(this.media == media) {
|
||||
return;
|
||||
}
|
||||
this.media = media;
|
||||
adapter.setMedia(media);
|
||||
adapter.notifyDataSetChanged();
|
||||
if(media == null || media.getChapters() == null || media.getChapters().size() == 0) {
|
||||
setEmptyText(getString(R.string.no_items_label));
|
||||
} else {
|
||||
setEmptyText(null);
|
||||
if (adapter != null) {
|
||||
adapter.setMedia(media);
|
||||
adapter.notifyDataSetChanged();
|
||||
if(media == null || media.getChapters() == null || media.getChapters().size() == 0) {
|
||||
setEmptyText(getString(R.string.no_items_label));
|
||||
} else {
|
||||
setEmptyText(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -215,9 +215,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
|||
onFragmentLoaded();
|
||||
}
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,22 +33,15 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra
|
|||
|
||||
public static CoverFragment newInstance(Playable item) {
|
||||
CoverFragment f = new CoverFragment();
|
||||
if (item != null) {
|
||||
Bundle args = new Bundle();
|
||||
args.putParcelable(ARG_PLAYABLE, item);
|
||||
f.setArguments(args);
|
||||
}
|
||||
f.media = item;
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Bundle args = getArguments();
|
||||
if (args != null) {
|
||||
media = args.getParcelable(ARG_PLAYABLE);
|
||||
} else {
|
||||
Log.e(TAG, TAG + " was called with invalid arguments");
|
||||
if (media == null) {
|
||||
Log.e(TAG, TAG + " was called without media");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +60,7 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra
|
|||
txtvPodcastTitle.setText(media.getFeedTitle());
|
||||
txtvEpisodeTitle.setText(media.getEpisodeTitle());
|
||||
Glide.with(this)
|
||||
.load(media.getImageUri())
|
||||
.load(media.getImageLocation())
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.dontAnimate()
|
||||
.fitCenter()
|
||||
|
@ -98,11 +91,13 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra
|
|||
|
||||
@Override
|
||||
public void onMediaChanged(Playable media) {
|
||||
if(!isAdded() || this.media == media) {
|
||||
if(this.media == media) {
|
||||
return;
|
||||
}
|
||||
this.media = media;
|
||||
loadMediaInfo();
|
||||
if (isAdded()) {
|
||||
loadMediaInfo();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -165,9 +165,7 @@ public class DownloadLogFragment extends ListFragment {
|
|||
onFragmentLoaded();
|
||||
}
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -79,6 +79,11 @@ public class EpisodesFragment extends Fragment {
|
|||
public static class EpisodesPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private final Resources resources;
|
||||
private AllEpisodesFragment[] fragments = {
|
||||
new NewEpisodesFragment(),
|
||||
new AllEpisodesFragment(),
|
||||
new FavoriteEpisodesFragment()
|
||||
};
|
||||
|
||||
public EpisodesPagerAdapter(FragmentManager fm, Resources resources) {
|
||||
super(fm);
|
||||
|
@ -87,15 +92,7 @@ public class EpisodesFragment extends Fragment {
|
|||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
switch (position) {
|
||||
case POS_ALL_EPISODES:
|
||||
return new AllEpisodesFragment();
|
||||
case POS_NEW_EPISODES:
|
||||
return new NewEpisodesFragment();
|
||||
case POS_FAV_EPISODES:
|
||||
return new FavoriteEpisodesFragment();
|
||||
}
|
||||
return null;
|
||||
return fragments[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -116,5 +113,14 @@ public class EpisodesFragment extends Fragment {
|
|||
return super.getPageTitle(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
super.setPrimaryItem(container, position, object);
|
||||
for (int i = 0; i < TOTAL_COUNT; i++) {
|
||||
// Invalidating the OptionsMenu is only allowed for the currently active fragment
|
||||
fragments[i].isMenuInvalidationAllowed = (i == position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ public class ExternalPlayerFragment extends Fragment {
|
|||
((double) controller.getPosition() / controller.getDuration() * 100));
|
||||
|
||||
Glide.with(getActivity())
|
||||
.load(media.getImageUri())
|
||||
.load(media.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
|
|
|
@ -71,9 +71,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
|||
|
||||
Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item),
|
||||
Snackbar.LENGTH_LONG);
|
||||
snackbar.setAction(getString(R.string.undo), v -> {
|
||||
DBWriter.addFavoriteItem(item);
|
||||
});
|
||||
snackbar.setAction(getString(R.string.undo), v -> DBWriter.addFavoriteItem(item));
|
||||
snackbar.show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.GridView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
|
||||
import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
|
||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.mfietz.fyydlin.FyydClient;
|
||||
import de.mfietz.fyydlin.FyydResponse;
|
||||
import de.mfietz.fyydlin.SearchHit;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
import static de.danoeh.antennapod.adapter.itunes.ItunesAdapter.Podcast;
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
public class FyydSearchFragment extends Fragment {
|
||||
|
||||
private static final String TAG = "FyydSearchFragment";
|
||||
|
||||
/**
|
||||
* Adapter responsible with the search results
|
||||
*/
|
||||
private ItunesAdapter adapter;
|
||||
private GridView gridView;
|
||||
private ProgressBar progressBar;
|
||||
private TextView txtvError;
|
||||
private Button butRetry;
|
||||
private TextView txtvEmpty;
|
||||
|
||||
private FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient());
|
||||
|
||||
/**
|
||||
* List of podcasts retreived from the search
|
||||
*/
|
||||
private List<Podcast> searchResults;
|
||||
private Subscription subscription;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public FyydSearchFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View root = inflater.inflate(R.layout.fragment_itunes_search, container, false);
|
||||
gridView = (GridView) root.findViewById(R.id.gridView);
|
||||
adapter = new ItunesAdapter(getActivity(), new ArrayList<>());
|
||||
gridView.setAdapter(adapter);
|
||||
|
||||
//Show information about the podcast when the list item is clicked
|
||||
gridView.setOnItemClickListener((parent, view1, position, id) -> {
|
||||
Podcast podcast = searchResults.get(position);
|
||||
Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
|
||||
intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl);
|
||||
intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, podcast.title);
|
||||
startActivity(intent);
|
||||
});
|
||||
progressBar = (ProgressBar) root.findViewById(R.id.progressBar);
|
||||
txtvError = (TextView) root.findViewById(R.id.txtvError);
|
||||
butRetry = (Button) root.findViewById(R.id.butRetry);
|
||||
txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
adapter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.itunes_search, menu);
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
MenuItemUtils.adjustTextColor(getActivity(), sv);
|
||||
sv.setQueryHint(getString(R.string.search_fyyd_label));
|
||||
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String s) {
|
||||
sv.clearFocus();
|
||||
search(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String s) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
|
||||
@Override
|
||||
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||
getActivity().getSupportFragmentManager().popBackStack();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
MenuItemCompat.expandActionView(searchItem);
|
||||
}
|
||||
|
||||
private void search(String query) {
|
||||
if (subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
showOnlyProgressBar();
|
||||
subscription = client.searchPodcasts(query)
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
processSearchResult(result);
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
progressBar.setVisibility(View.GONE);
|
||||
txtvError.setText(error.toString());
|
||||
txtvError.setVisibility(View.VISIBLE);
|
||||
butRetry.setOnClickListener(v -> search(query));
|
||||
butRetry.setVisibility(View.VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
private void showOnlyProgressBar() {
|
||||
gridView.setVisibility(View.GONE);
|
||||
txtvError.setVisibility(View.GONE);
|
||||
butRetry.setVisibility(View.GONE);
|
||||
txtvEmpty.setVisibility(View.GONE);
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
void processSearchResult(FyydResponse response) {
|
||||
adapter.clear();
|
||||
if (!response.getData().isEmpty()) {
|
||||
adapter.clear();
|
||||
searchResults = new ArrayList<>();
|
||||
for (SearchHit searchHit : response.getData().values()) {
|
||||
Podcast podcast = Podcast.fromSearch(searchHit);
|
||||
searchResults.add(podcast);
|
||||
}
|
||||
} else {
|
||||
searchResults = emptyList();
|
||||
}
|
||||
for(Podcast podcast : searchResults) {
|
||||
adapter.add(podcast);
|
||||
}
|
||||
adapter.notifyDataSetInvalidated();
|
||||
gridView.setVisibility(!searchResults.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
txtvEmpty.setVisibility(searchResults.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
}
|
|
@ -185,8 +185,10 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
|
|||
super.onViewCreated(view, savedInstanceState);
|
||||
Bundle args = getArguments();
|
||||
if (args.containsKey(ARG_PLAYABLE)) {
|
||||
media = args.getParcelable(ARG_PLAYABLE);
|
||||
shownotesProvider = media;
|
||||
if (media == null) {
|
||||
media = args.getParcelable(ARG_PLAYABLE);
|
||||
shownotesProvider = media;
|
||||
}
|
||||
load();
|
||||
} else if (args.containsKey(ARG_FEEDITEM_ID)) {
|
||||
long id = getArguments().getLong(ARG_FEEDITEM_ID);
|
||||
|
@ -196,9 +198,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
|
|||
.subscribe(feedItem -> {
|
||||
shownotesProvider = feedItem;
|
||||
load();
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,9 +311,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
|
|||
webvDescription.loadDataWithBaseURL(null, data, "text/html",
|
||||
"utf-8", "about:blank");
|
||||
Log.d(TAG, "Webview loaded");
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private String loadData() {
|
||||
|
@ -348,7 +346,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
|
|||
}
|
||||
|
||||
private boolean restoreFromPreference() {
|
||||
if (!saveState) {
|
||||
if (saveState) {
|
||||
Log.d(TAG, "Restoring from preferences");
|
||||
Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
|
@ -381,12 +379,14 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
|
|||
|
||||
@Override
|
||||
public void onMediaChanged(Playable media) {
|
||||
if(this.media == media || webvDescription == null) {
|
||||
if(this.media == media) {
|
||||
return;
|
||||
}
|
||||
this.media = media;
|
||||
this.shownotesProvider = media;
|
||||
load();
|
||||
if (webvDescription != null) {
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,9 +44,7 @@ import de.danoeh.antennapod.activity.MainActivity;
|
|||
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
|
||||
import de.danoeh.antennapod.core.event.DownloadEvent;
|
||||
import de.danoeh.antennapod.core.event.DownloaderUpdate;
|
||||
import de.danoeh.antennapod.core.event.FavoritesEvent;
|
||||
import de.danoeh.antennapod.core.event.FeedItemEvent;
|
||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
|
@ -60,7 +58,9 @@ import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
|||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.Converter;
|
||||
import de.danoeh.antennapod.core.util.DateUtils;
|
||||
import de.danoeh.antennapod.core.util.Flavors;
|
||||
import de.danoeh.antennapod.core.util.IntentUtils;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
import de.danoeh.antennapod.core.util.ShareUtils;
|
||||
import de.danoeh.antennapod.core.util.playback.Timeline;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
|
@ -222,7 +222,8 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
|
|||
return;
|
||||
}
|
||||
DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getActivity());
|
||||
actionButtonCallback.onActionButtonPressed(item);
|
||||
actionButtonCallback.onActionButtonPressed(item, item.isTagged(FeedItem.TAG_QUEUE) ?
|
||||
LongList.of(item.getId()) : new LongList(0));
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media != null && media.isDownloaded()) {
|
||||
// playback was started, dialog should close itself
|
||||
|
@ -312,7 +313,10 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
|
|||
if(!isAdded() || item == null) {
|
||||
return;
|
||||
}
|
||||
((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
if (Flavors.FLAVOR == Flavors.PLAY) {
|
||||
((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
}
|
||||
inflater.inflate(R.menu.feeditem_options, menu);
|
||||
popupMenu = menu;
|
||||
if (item.hasMedia()) {
|
||||
|
@ -374,7 +378,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
|
|||
}
|
||||
|
||||
Glide.with(getActivity())
|
||||
.load(item.getImageUri())
|
||||
.load(item.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
|
@ -417,7 +421,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
|
|||
butAction2Text = R.string.stream_label;
|
||||
} else {
|
||||
butAction2Icon = "{md-delete 24sp}";
|
||||
butAction2Text = R.string.remove_label;
|
||||
butAction2Text = R.string.delete_label;
|
||||
}
|
||||
if (isDownloading) {
|
||||
butAction1Icon = "{md-cancel 24sp}";
|
||||
|
@ -576,9 +580,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
|
|||
item = result;
|
||||
itemsLoaded = true;
|
||||
onFragmentLoaded();
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private FeedItem loadInBackground() {
|
||||
|
|
|
@ -64,8 +64,10 @@ import de.danoeh.antennapod.core.storage.DBTasks;
|
|||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
|
||||
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
|
||||
import de.danoeh.antennapod.dialog.RenameFeedDialog;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
|
@ -98,6 +100,7 @@ public class ItemlistFragment extends ListFragment {
|
|||
|
||||
private boolean itemsLoaded = false;
|
||||
private boolean viewsCreated = false;
|
||||
private boolean headerCreated = false;
|
||||
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
|
@ -105,7 +108,10 @@ public class ItemlistFragment extends ListFragment {
|
|||
|
||||
private boolean isUpdatingFeed;
|
||||
|
||||
private TextView txtvTitle;
|
||||
private IconTextView txtvFailure;
|
||||
private ImageView imgvBackground;
|
||||
private ImageView imgvCover;
|
||||
|
||||
private TextView txtvInformation;
|
||||
|
||||
|
@ -247,6 +253,9 @@ public class ItemlistFragment extends ListFragment {
|
|||
.newInstance(feed.getItems());
|
||||
((MainActivity)getActivity()).loadChildFragment(fragment);
|
||||
return true;
|
||||
case R.id.rename_item:
|
||||
new RenameFeedDialog(getActivity(), feed).show();
|
||||
return true;
|
||||
case R.id.remove_item:
|
||||
final FeedRemover remover = new FeedRemover(
|
||||
getActivity(), feed) {
|
||||
|
@ -258,7 +267,7 @@ public class ItemlistFragment extends ListFragment {
|
|||
};
|
||||
ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(),
|
||||
R.string.remove_feed_label,
|
||||
R.string.feed_delete_confirmation_msg) {
|
||||
getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(
|
||||
|
@ -414,6 +423,7 @@ public class ItemlistFragment extends ListFragment {
|
|||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((EVENTS & arg) != 0) {
|
||||
Log.d(TAG, "Received contentUpdate Intent. arg " + arg);
|
||||
refreshHeaderView();
|
||||
loadItems();
|
||||
updateProgressBarVisibility();
|
||||
}
|
||||
|
@ -459,15 +469,17 @@ public class ItemlistFragment extends ListFragment {
|
|||
}
|
||||
|
||||
private void refreshHeaderView() {
|
||||
if (getListView() == null || feed == null) {
|
||||
Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
|
||||
if (getListView() == null || feed == null || !headerCreated) {
|
||||
Log.e(TAG, "Unable to refresh header view");
|
||||
return;
|
||||
}
|
||||
loadFeedImage();
|
||||
if(feed.hasLastUpdateFailed()) {
|
||||
txtvFailure.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
txtvFailure.setVisibility(View.GONE);
|
||||
}
|
||||
txtvTitle.setText(feed.getTitle());
|
||||
if(feed.getItemFilter() != null) {
|
||||
FeedItemFilter filter = feed.getItemFilter();
|
||||
if(filter.getValues().length > 0) {
|
||||
|
@ -497,10 +509,10 @@ public class ItemlistFragment extends ListFragment {
|
|||
View header = inflater.inflate(R.layout.feeditemlist_header, lv, false);
|
||||
lv.addHeaderView(header);
|
||||
|
||||
TextView txtvTitle = (TextView) header.findViewById(R.id.txtvTitle);
|
||||
txtvTitle = (TextView) header.findViewById(R.id.txtvTitle);
|
||||
TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor);
|
||||
ImageView imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground);
|
||||
ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
|
||||
imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground);
|
||||
imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
|
||||
ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo);
|
||||
txtvInformation = (TextView) header.findViewById(R.id.txtvInformation);
|
||||
txtvFailure = (IconTextView) header.findViewById(R.id.txtvFailure);
|
||||
|
@ -512,23 +524,7 @@ public class ItemlistFragment extends ListFragment {
|
|||
// https://github.com/bumptech/glide/issues/529
|
||||
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
|
||||
|
||||
Glide.with(getActivity())
|
||||
.load(feed.getImageUri())
|
||||
.placeholder(R.color.image_readability_tint)
|
||||
.error(R.color.image_readability_tint)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.transform(new FastBlurTransformation(getActivity()))
|
||||
.dontAnimate()
|
||||
.into(imgvBackground);
|
||||
|
||||
Glide.with(getActivity())
|
||||
.load(feed.getImageUri())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(imgvCover);
|
||||
loadFeedImage();
|
||||
|
||||
butShowInfo.setOnClickListener(v -> {
|
||||
if (viewsCreated && itemsLoaded) {
|
||||
|
@ -538,6 +534,27 @@ public class ItemlistFragment extends ListFragment {
|
|||
startActivity(startIntent);
|
||||
}
|
||||
});
|
||||
headerCreated = true;
|
||||
}
|
||||
|
||||
private void loadFeedImage() {
|
||||
Glide.with(getActivity())
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.image_readability_tint)
|
||||
.error(R.color.image_readability_tint)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.transform(new FastBlurTransformation(getActivity()))
|
||||
.dontAnimate()
|
||||
.into(imgvBackground);
|
||||
|
||||
Glide.with(getActivity())
|
||||
.load(feed.getImageLocation())
|
||||
.placeholder(R.color.light_gray)
|
||||
.error(R.color.light_gray)
|
||||
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
|
||||
.fitCenter()
|
||||
.dontAnimate()
|
||||
.into(imgvCover);
|
||||
}
|
||||
|
||||
|
||||
|
@ -577,6 +594,20 @@ public class ItemlistFragment extends ListFragment {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongList getQueueIds() {
|
||||
LongList queueIds = new LongList();
|
||||
if(feed == null) {
|
||||
return queueIds;
|
||||
}
|
||||
for(FeedItem item : feed.getItems()) {
|
||||
if(item.isTagged(FeedItem.TAG_QUEUE)) {
|
||||
queueIds.add(item.getId());
|
||||
}
|
||||
}
|
||||
return queueIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return (feed != null) ? feed.getNumOfItems() : 0;
|
||||
|
@ -612,9 +643,7 @@ public class ItemlistFragment extends ListFragment {
|
|||
onFragmentLoaded();
|
||||
}
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private Feed loadData() {
|
||||
|
|
|
@ -18,9 +18,6 @@ import android.widget.ProgressBar;
|
|||
import android.widget.TextView;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Response;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
@ -39,6 +36,9 @@ import de.danoeh.antennapod.adapter.itunes.ItunesAdapter;
|
|||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
|
|
|
@ -7,6 +7,8 @@ import android.support.v7.widget.RecyclerView;
|
|||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
|
@ -92,7 +94,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
|
|||
}
|
||||
};
|
||||
|
||||
Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label),
|
||||
Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_seen_label),
|
||||
Snackbar.LENGTH_LONG);
|
||||
snackbar.setAction(getString(R.string.undo), v -> {
|
||||
DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
|
||||
|
|
|
@ -28,6 +28,7 @@ import de.danoeh.antennapod.core.service.download.Downloader;
|
|||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
import de.greenrobot.event.EventBus;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
|
@ -251,6 +252,20 @@ public class PlaybackHistoryFragment extends ListFragment {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongList getQueueIds() {
|
||||
LongList queueIds = new LongList();
|
||||
if(playbackHistory == null) {
|
||||
return queueIds;
|
||||
}
|
||||
for (FeedItem item : playbackHistory) {
|
||||
if (item.isTagged(FeedItem.TAG_QUEUE)) {
|
||||
queueIds.add(item.getId());
|
||||
}
|
||||
}
|
||||
return queueIds;
|
||||
}
|
||||
};
|
||||
|
||||
private void loadItems() {
|
||||
|
@ -268,9 +283,7 @@ public class PlaybackHistoryFragment extends ListFragment {
|
|||
onFragmentLoaded();
|
||||
}
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private List<FeedItem> loadData() {
|
||||
|
|
|
@ -304,11 +304,11 @@ public class QueueFragment extends Fragment {
|
|||
};
|
||||
conDialog.createNewDialog().show();
|
||||
return true;
|
||||
case R.id.queue_sort_alpha_asc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_ASC, true);
|
||||
case R.id.queue_sort_episode_title_asc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_ASC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_alpha_desc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_DESC, true);
|
||||
case R.id.queue_sort_episode_title_desc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.EPISODE_TITLE_DESC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_date_asc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DATE_ASC, true);
|
||||
|
@ -322,6 +322,12 @@ public class QueueFragment extends Fragment {
|
|||
case R.id.queue_sort_duration_desc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DURATION_DESC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_feed_title_asc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_ASC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_feed_title_desc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_DESC, true);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -605,9 +611,7 @@ public class QueueFragment extends Fragment {
|
|||
recyclerAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -182,6 +182,9 @@ public class SearchFragment extends ListFragment {
|
|||
}
|
||||
searchAdapter.notifyDataSetChanged();
|
||||
setListShown(true);
|
||||
|
||||
String query = getArguments().getString(ARG_QUERY);
|
||||
setEmptyText(getString(R.string.no_results_for_query, query));
|
||||
}
|
||||
|
||||
private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() {
|
||||
|
@ -219,9 +222,7 @@ public class SearchFragment extends ListFragment {
|
|||
onFragmentLoaded();
|
||||
}
|
||||
}
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private List<SearchResult> performSearch() {
|
||||
|
|
|
@ -26,7 +26,9 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
|||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||
import de.danoeh.antennapod.dialog.RenameFeedDialog;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
|
@ -46,6 +48,7 @@ public class SubscriptionFragment extends Fragment {
|
|||
|
||||
private int mPosition = -1;
|
||||
|
||||
private Subscription subscription;
|
||||
|
||||
public SubscriptionFragment() {
|
||||
}
|
||||
|
@ -88,16 +91,25 @@ public class SubscriptionFragment extends Fragment {
|
|||
EventDistributor.getInstance().register(contentUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSubscriptions() {
|
||||
Observable.fromCallable(() -> DBReader.getNavDrawerData())
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
subscription = Observable.fromCallable(DBReader::getNavDrawerData)
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
navDrawerData = result;
|
||||
subscriptionAdapter.notifyDataSetChanged();
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -143,21 +155,18 @@ public class SubscriptionFragment extends Fragment {
|
|||
Observable.fromCallable(() -> DBWriter.markFeedSeen(feed.getId()))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
loadSubscriptions();
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
.subscribe(result -> loadSubscriptions(),
|
||||
error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
return true;
|
||||
case R.id.mark_all_read_item:
|
||||
Observable.fromCallable(() -> DBWriter.markFeedRead(feed.getId()))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
loadSubscriptions();
|
||||
}, error -> {
|
||||
Log.e(TAG, Log.getStackTraceString(error));
|
||||
});
|
||||
.subscribe(result -> loadSubscriptions(),
|
||||
error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
return true;
|
||||
case R.id.rename_item:
|
||||
new RenameFeedDialog(getActivity(), feed).show();
|
||||
return true;
|
||||
case R.id.remove_item:
|
||||
final FeedRemover remover = new FeedRemover(getContext(), feed) {
|
||||
|
@ -169,7 +178,7 @@ public class SubscriptionFragment extends Fragment {
|
|||
};
|
||||
ConfirmationDialog conDialog = new ConfirmationDialog(getContext(),
|
||||
R.string.remove_feed_label,
|
||||
R.string.feed_delete_confirmation_msg) {
|
||||
getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
|
||||
@Override
|
||||
public void onConfirmButtonPressed(
|
||||
DialogInterface dialog) {
|
||||
|
|
|
@ -80,7 +80,7 @@ public class FeedItemMenuHandler {
|
|||
if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId()) {
|
||||
mi.setItemVisibility(R.id.move_to_bottom_item, false);
|
||||
}
|
||||
if (!isInQueue || isPlaying) {
|
||||
if (!isInQueue) {
|
||||
mi.setItemVisibility(R.id.remove_from_queue_item, false);
|
||||
}
|
||||
if (!(!isInQueue && selectedItem.getMedia() != null)) {
|
||||
|
@ -101,6 +101,8 @@ public class FeedItemMenuHandler {
|
|||
mi.setItemVisibility(R.id.share_download_url_with_position_item, false);
|
||||
}
|
||||
|
||||
mi.setItemVisibility(R.id.share_file, hasMedia && selectedItem.getMedia().fileExists());
|
||||
|
||||
if (selectedItem.isPlayed()) {
|
||||
mi.setItemVisibility(R.id.mark_read_item, false);
|
||||
} else {
|
||||
|
@ -239,6 +241,9 @@ public class FeedItemMenuHandler {
|
|||
case R.id.share_download_url_with_position_item:
|
||||
ShareUtils.shareFeedItemDownloadLink(context, selectedItem, true);
|
||||
break;
|
||||
case R.id.share_file:
|
||||
ShareUtils.shareFeedItemFile(context, selectedItem.getMedia());
|
||||
break;
|
||||
default:
|
||||
Log.d(TAG, "Unknown menuItemId: " + menuItemId);
|
||||
return false;
|
||||
|
|
|
@ -28,6 +28,7 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ResourceType")
|
||||
public static void refreshLockItem(Context context, Menu menu) {
|
||||
final MenuItem queueLock = menu.findItem(de.danoeh.antennapod.R.id.queue_lock);
|
||||
int[] lockIcons = new int[] { de.danoeh.antennapod.R.attr.ic_lock_open, de.danoeh.antennapod.R.attr.ic_lock_closed };
|
||||
|
|
|
@ -3,6 +3,7 @@ package de.danoeh.antennapod.preferences;
|
|||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.TimePickerDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
|
@ -28,14 +29,13 @@ import android.text.Editable;
|
|||
import android.text.Html;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.format.DateFormat;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
|
@ -43,6 +43,8 @@ import java.io.File;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -52,10 +54,14 @@ import de.danoeh.antennapod.R;
|
|||
import de.danoeh.antennapod.activity.AboutActivity;
|
||||
import de.danoeh.antennapod.activity.DirectoryChooserActivity;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.activity.MediaplayerActivity;
|
||||
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||
import de.danoeh.antennapod.activity.PreferenceActivityGingerbread;
|
||||
import de.danoeh.antennapod.activity.StatisticsActivity;
|
||||
import de.danoeh.antennapod.asynctask.OpmlExportWorker;
|
||||
import de.danoeh.antennapod.asynctask.ExportWorker;
|
||||
import de.danoeh.antennapod.core.export.ExportWriter;
|
||||
import de.danoeh.antennapod.core.export.html.HtmlWriter;
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlWriter;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.GpodnetSyncService;
|
||||
|
@ -67,6 +73,10 @@ import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
|
|||
import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
|
||||
import de.danoeh.antennapod.dialog.ProxyDialog;
|
||||
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||
import rx.Observable;
|
||||
import rx.Subscription;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Sets up a preference UI that lets the user change user preferences.
|
||||
|
@ -76,35 +86,45 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
|
||||
private static final String TAG = "PreferenceController";
|
||||
|
||||
public static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
|
||||
public static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
|
||||
public static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
|
||||
public static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
|
||||
public static final String PREF_OPML_EXPORT = "prefOpmlExport";
|
||||
public static final String STATISTICS = "statistics";
|
||||
public static final String PREF_ABOUT = "prefAbout";
|
||||
public static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
|
||||
public static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
|
||||
public static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
|
||||
public static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
|
||||
public static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
|
||||
public static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
|
||||
public static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
|
||||
public static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
|
||||
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
|
||||
public static final String PREF_PROXY = "prefProxy";
|
||||
public static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
|
||||
public static final String PREF_FAQ = "prefFaq";
|
||||
public static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
|
||||
|
||||
private final PreferenceUI ui;
|
||||
|
||||
private CheckBoxPreference[] selectedNetworks;
|
||||
|
||||
private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
|
||||
private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
|
||||
private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
|
||||
private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
|
||||
private static final String PREF_OPML_EXPORT = "prefOpmlExport";
|
||||
private static final String PREF_HTML_EXPORT = "prefHtmlExport";
|
||||
private static final String STATISTICS = "statistics";
|
||||
private static final String PREF_ABOUT = "prefAbout";
|
||||
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
|
||||
private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
|
||||
private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
|
||||
public static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher";
|
||||
public static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher";
|
||||
private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
|
||||
private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
|
||||
private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
|
||||
private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync";
|
||||
private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
|
||||
private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
|
||||
private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications";
|
||||
private static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
|
||||
private static final String PREF_PROXY = "prefProxy";
|
||||
private static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
|
||||
private static final String PREF_FAQ = "prefFaq";
|
||||
private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
|
||||
private static final String[] EXTERNAL_STORAGE_PERMISSIONS = {
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE };
|
||||
private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41;
|
||||
private final PreferenceUI ui;
|
||||
private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener =
|
||||
(sharedPreferences, key) -> {
|
||||
if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) {
|
||||
updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(),
|
||||
GpodnetPreferences.getLastSyncAttemptTimestamp());
|
||||
}
|
||||
};
|
||||
private CheckBoxPreference[] selectedNetworks;
|
||||
private Subscription subscription;
|
||||
|
||||
public PreferenceController(PreferenceUI ui) {
|
||||
this.ui = ui;
|
||||
|
@ -112,6 +132,19 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
.registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preference activity that should be used on this device.
|
||||
*
|
||||
* @return PreferenceActivity if the API level is greater than 10, PreferenceActivityGingerbread otherwise.
|
||||
*/
|
||||
public static Class<? extends Activity> getPreferenceActivity() {
|
||||
if (Build.VERSION.SDK_INT > 10) {
|
||||
return PreferenceActivity.class;
|
||||
} else {
|
||||
return PreferenceActivityGingerbread.class;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if(key.equals(UserPreferences.PREF_SONIC)) {
|
||||
|
@ -122,19 +155,6 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preference activity that should be used on this device.
|
||||
*
|
||||
* @return PreferenceActivity if the API level is greater than 10, PreferenceActivityGingerbread otherwise.
|
||||
*/
|
||||
public static Class getPreferenceActivity() {
|
||||
if (Build.VERSION.SDK_INT > 10) {
|
||||
return PreferenceActivity.class;
|
||||
} else {
|
||||
return PreferenceActivityGingerbread.class;
|
||||
}
|
||||
}
|
||||
|
||||
public void onCreate() {
|
||||
final Activity activity = ui.getActivity();
|
||||
|
||||
|
@ -170,11 +190,9 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
}
|
||||
);
|
||||
ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
new OpmlExportWorker(activity).executeAsync();
|
||||
return true;
|
||||
}
|
||||
);
|
||||
preference -> export(new OpmlWriter()));
|
||||
ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener(
|
||||
preference -> export(new HtmlWriter()));
|
||||
ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT &&
|
||||
|
@ -318,6 +336,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
VariableSpeedDialog.showDialog(activity);
|
||||
return true;
|
||||
});
|
||||
ui.findPreference(PreferenceController.PREF_PLAYBACK_REWIND_DELTA_LAUNCHER)
|
||||
.setOnPreferenceClickListener(preference -> {
|
||||
MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_REWIND);
|
||||
return true;
|
||||
});
|
||||
ui.findPreference(PreferenceController.PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER)
|
||||
.setOnPreferenceClickListener(preference -> {
|
||||
MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD);
|
||||
return true;
|
||||
});
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION)
|
||||
.setOnPreferenceClickListener(preference -> {
|
||||
AuthenticationDialog dialog = new AuthenticationDialog(activity,
|
||||
|
@ -340,6 +368,18 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
toast.show();
|
||||
return true;
|
||||
});
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).
|
||||
setOnPreferenceClickListener(preference -> {
|
||||
GpodnetPreferences.setLastSubscriptionSyncTimestamp(0L);
|
||||
GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(0L);
|
||||
GpodnetPreferences.setLastSyncAttempt(false, 0);
|
||||
updateLastGpodnetSyncReport(false, 0);
|
||||
GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext());
|
||||
Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started,
|
||||
Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
return true;
|
||||
});
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
GpodnetPreferences.logout();
|
||||
|
@ -412,28 +452,47 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle));
|
||||
return true;
|
||||
});
|
||||
//checks whether Google Play Services is installed on the device (condition necessary for Cast support)
|
||||
ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setOnPreferenceChangeListener((preference, o) -> {
|
||||
if (o instanceof Boolean && ((Boolean) o)) {
|
||||
final int googlePlayServicesCheck = GoogleApiAvailability.getInstance()
|
||||
.isGooglePlayServicesAvailable(ui.getActivity());
|
||||
if (googlePlayServicesCheck == ConnectionResult.SUCCESS) {
|
||||
return true;
|
||||
} else {
|
||||
GoogleApiAvailability.getInstance()
|
||||
.getErrorDialog(ui.getActivity(), googlePlayServicesCheck, 0)
|
||||
.show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
PreferenceControllerFlavorHelper.setupFlavoredUI(ui);
|
||||
buildEpisodeCleanupPreference();
|
||||
buildSmartMarkAsPlayedPreference();
|
||||
buildAutodownloadSelectedNetworsPreference();
|
||||
setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter());
|
||||
}
|
||||
|
||||
private boolean export(ExportWriter exportWriter) {
|
||||
Context context = ui.getActivity();
|
||||
final ProgressDialog progressDialog = new ProgressDialog(context);
|
||||
progressDialog.setMessage(context.getString(R.string.exporting_label));
|
||||
progressDialog.setIndeterminate(true);
|
||||
progressDialog.show();
|
||||
final AlertDialog.Builder alert = new AlertDialog.Builder(context)
|
||||
.setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss());
|
||||
Observable<File> observable = new ExportWorker(exportWriter).exportObservable();
|
||||
subscription = observable.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(output -> {
|
||||
alert.setTitle(R.string.opml_export_success_title);
|
||||
String message = context.getString(R.string.opml_export_success_sum) + output.toString();
|
||||
alert.setMessage(message);
|
||||
alert.setPositiveButton(R.string.send_label, (dialog, which) -> {
|
||||
Uri outputUri = Uri.fromFile(output);
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT,
|
||||
context.getResources().getText(R.string.opml_export_label));
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri);
|
||||
sendIntent.setType("text/plain");
|
||||
context.startActivity(Intent.createChooser(sendIntent,
|
||||
context.getResources().getText(R.string.send_label)));
|
||||
});
|
||||
alert.create().show();
|
||||
}, error -> {
|
||||
alert.setTitle(R.string.export_error_label);
|
||||
alert.setMessage(error.getMessage());
|
||||
alert.show();
|
||||
}, () -> progressDialog.dismiss());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void openInBrowser(String url) {
|
||||
try {
|
||||
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
|
@ -450,9 +509,20 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
setParallelDownloadsText(UserPreferences.getParallelDownloads());
|
||||
setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize());
|
||||
setDataFolderText();
|
||||
GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener);
|
||||
updateGpodnetPreferenceScreen();
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener);
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
if(subscription != null) {
|
||||
subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == Activity.RESULT_OK &&
|
||||
|
@ -494,18 +564,41 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn);
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn);
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).setEnabled(loggedIn);
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn);
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setEnabled(loggedIn);
|
||||
ui.findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn);
|
||||
if(loggedIn) {
|
||||
String format = ui.getActivity().getString(R.string.pref_gpodnet_login_status);
|
||||
String summary = String.format(format, GpodnetPreferences.getUsername(),
|
||||
GpodnetPreferences.getDeviceID());
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary));
|
||||
updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(),
|
||||
GpodnetPreferences.getLastSyncAttemptTimestamp());
|
||||
} else {
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(null);
|
||||
updateLastGpodnetSyncReport(false, 0);
|
||||
}
|
||||
ui.findPreference(PreferenceController.PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname());
|
||||
}
|
||||
|
||||
private void updateLastGpodnetSyncReport(boolean successful, long lastTime) {
|
||||
Preference sync = ui.findPreference(PREF_GPODNET_SYNC);
|
||||
if (lastTime != 0) {
|
||||
sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" +
|
||||
ui.getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line,
|
||||
ui.getActivity().getString(successful ?
|
||||
R.string.gpodnetsync_pref_report_successful :
|
||||
R.string.gpodnetsync_pref_report_failed),
|
||||
DateUtils.getRelativeDateTimeString(ui.getActivity(),
|
||||
lastTime,
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.WEEK_IN_MILLIS,
|
||||
DateUtils.FORMAT_SHOW_TIME)));
|
||||
} else {
|
||||
sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum));
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getUpdateIntervalEntries(final String[] values) {
|
||||
final Resources res = ui.getActivity().getResources();
|
||||
String[] entries = new String[values.length];
|
||||
|
@ -621,7 +714,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
val = String.format(context.getString(R.string.pref_autoUpdateIntervallOrTime_at),
|
||||
timeOfDayStr);
|
||||
} else {
|
||||
val = context.getString(R.string.pref_smart_mark_as_played_disabled);
|
||||
val = context.getString(R.string.pref_smart_mark_as_played_disabled); // TODO: Is this a bug? Otherwise document why is this related to smart mark???
|
||||
}
|
||||
}
|
||||
String summary = context.getString(R.string.pref_autoUpdateIntervallOrTime_sum) + "\n"
|
||||
|
@ -666,10 +759,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
clearAutodownloadSelectedNetworsPreference();
|
||||
}
|
||||
// get configured networks
|
||||
WifiManager wifiservice = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
|
||||
WifiManager wifiservice = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
List<WifiConfiguration> networks = wifiservice.getConfiguredNetworks();
|
||||
|
||||
if (networks != null) {
|
||||
Collections.sort(networks, new Comparator<WifiConfiguration>() {
|
||||
@Override
|
||||
public int compare(WifiConfiguration x, WifiConfiguration y) {
|
||||
return x.SSID.compareTo(y.SSID);
|
||||
}
|
||||
});
|
||||
selectedNetworks = new CheckBoxPreference[networks.size()];
|
||||
List<String> prefValues = Arrays.asList(UserPreferences
|
||||
.getAutodownloadSelectedNetworks());
|
||||
|
@ -754,9 +853,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||
UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
|
||||
UserPreferences.setHiddenDrawerItems(hiddenDrawerItems));
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.create().show();
|
||||
}
|
||||
|
@ -800,9 +898,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
|||
preferredButtons.remove((Integer) which);
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
|
||||
UserPreferences.setCompactNotificationButtons(preferredButtons);
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
|
||||
UserPreferences.setCompactNotificationButtons(preferredButtons));
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.create().show();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
Easy-to-use, flexible and open-source podcast manager and player
|
||||
|
||||
AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
|
||||
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
|
||||
|
||||
|
@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod
|
|||
Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
|
||||
https://groups.google.com/forum/#!forum/antennapod
|
||||
|
||||
Have a question or want to give us feedback?
|
||||
https://twitter.com/@AntennaPod
|
||||
|
||||
Transifex is the place to help with translations:<br>
|
||||
https://www.transifex.com/antennapod/antennapod
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
Easy-to-use, flexible and open-source podcast manager and player
|
||||
|
||||
AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
|
||||
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
|
||||
|
||||
|
@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod
|
|||
Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
|
||||
https://groups.google.com/forum/#!forum/antennapod
|
||||
|
||||
Have a question or want to give us feedback?
|
||||
https://twitter.com/@AntennaPod
|
||||
|
||||
Transifex is the place to help with translations:<br>
|
||||
https://www.transifex.com/antennapod/antennapod
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
Easy-to-use, flexible and open-source podcast manager and player
|
||||
|
||||
AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
|
||||
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
|
||||
|
||||
|
@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod
|
|||
Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
|
||||
https://groups.google.com/forum/#!forum/antennapod
|
||||
|
||||
Have a question or want to give us feedback?
|
||||
https://twitter.com/@AntennaPod
|
||||
|
||||
Transifex is the place to help with translations:<br>
|
||||
https://www.transifex.com/antennapod/antennapod
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
Easy-to-use, flexible and open-source podcast manager and player
|
||||
|
||||
AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
|
||||
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
|
||||
|
||||
|
@ -35,6 +33,9 @@ https://www.github.com/AntennaPod/AntennaPod
|
|||
Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
|
||||
https://groups.google.com/forum/#!forum/antennapod
|
||||
|
||||
Have a question or want to give us feedback?
|
||||
https://twitter.com/@AntennaPod
|
||||
|
||||
Transifex is the place to help with translations:<br>
|
||||
https://www.transifex.com/antennapod/antennapod
|
||||
|
|
@ -0,0 +1 @@
|
|||
Easy-to-use, flexible and open-source podcast manager and player
|
|
@ -0,0 +1 @@
|
|||
AntennaPod
|
|
@ -0,0 +1,11 @@
|
|||
* New features:
|
||||
* Subscription overview
|
||||
* Proxy support
|
||||
* Statistics
|
||||
* Manual gpodder.net sync
|
||||
* Fixes:
|
||||
* Audioplayer controls
|
||||
* Audio ducking
|
||||
* Video control fade-out
|
||||
* External media controls
|
||||
* Feed parsing
|
|
@ -0,0 +1,43 @@
|
|||
AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
|
||||
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
|
||||
|
||||
Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
|
||||
|
||||
<b>All features:</b><br>
|
||||
IMPORT, ORGANIZE AND PLAY<br>
|
||||
• Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
|
||||
• Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
|
||||
• Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
|
||||
• Access password-protected feeds and episodes<br>
|
||||
• Take advantage of paged feeds (www.podlove.org/paged-feeds)
|
||||
|
||||
KEEP TRACK, SHARE & APPRECIATE<br>
|
||||
• Keep track of the best of the best by marking episodes as favourites<br>
|
||||
• Find that one episode through the playback history or by searching (titles and shownotes)<br>
|
||||
• Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
|
||||
• Support content creators with Flattr integration including automatic flattring
|
||||
|
||||
CONTROL THE SYSTEM<br>
|
||||
• Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
|
||||
• Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
|
||||
• Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
|
||||
• Adapt to your environment using the light and dark theme<br>
|
||||
• Back-up your subscriptions with the gPodder.net integration and OPML export
|
||||
|
||||
<b>Join the AntennaPod community!</b><br>
|
||||
AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
|
||||
|
||||
GitHub is the place to go for feature requests, bug reports and code contributions:<br>
|
||||
https://www.github.com/AntennaPod/AntennaPod
|
||||
|
||||
Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
|
||||
https://groups.google.com/forum/#!forum/antennapod
|
||||
|
||||
Have a question or want to give us feedback?
|
||||
https://twitter.com/@AntennaPod
|
||||
|
||||
Transifex is the place to help with translations:<br>
|
||||
https://www.transifex.com/antennapod/antennapod
|
||||
|
||||
Check out our Beta Testing programme to get the latest features first:<br>
|
||||
https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod
|
|
@ -0,0 +1 @@
|
|||
antennapod@googlegroups.com
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue