summaryrefslogtreecommitdiff
path: root/core/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java97
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java94
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/receiver/MediaButtonReceiver.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java32
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java32
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java111
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/Converter.java23
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java16
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/IntList.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/gui/FeedItemUndoToken.java55
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java56
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java62
23 files changed, 476 insertions, 211 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
index 6619e706b..a96affb23 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
@@ -1,5 +1,12 @@
package de.danoeh.antennapod.core;
+import android.content.Context;
+
+import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import de.danoeh.antennapod.core.util.NetworkUtils;
+
/**
* Stores callbacks for core classes like Services, DB classes etc. and other configuration variables.
* Apps using the core module of AntennaPod should register implementations of all interfaces here.
@@ -22,4 +29,19 @@ public class ClientConfig {
public static FlattrCallbacks flattrCallbacks;
public static DBTasksCallbacks dbTasksCallbacks;
+
+ private static boolean initialized = false;
+
+ public static synchronized void initialize(Context context) {
+ if(initialized) {
+ return;
+ }
+ PodDBAdapter.init(context);
+ UserPreferences.init(context);
+ UpdateManager.init(context);
+ PlaybackPreferences.init(context);
+ NetworkUtils.init(context);
+ initialized = true;
+ }
+
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java b/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java
new file mode 100644
index 000000000..8362c4a4e
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java
@@ -0,0 +1,97 @@
+package de.danoeh.antennapod.core;
+
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.util.Log;
+
+import org.antennapod.audio.MediaPlayer;
+
+import java.io.File;
+import java.util.List;
+
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedImage;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
+
+/*
+ * This class's job is do perform maintenance tasks whenever the app has been updated
+ */
+public class UpdateManager {
+
+ public static final String TAG = UpdateManager.class.getSimpleName();
+
+ private static final String PREF_NAME = "app_version";
+ private static final String KEY_VERSION_CODE = "version_code";
+
+ private static int currentVersionCode;
+
+ private static Context context;
+ private static SharedPreferences prefs;
+
+ public static void init(Context context) {
+ UpdateManager.context = context;
+ prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
+ PackageManager pm = context.getPackageManager();
+ try {
+ PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
+ currentVersionCode = info.versionCode;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Failed to obtain package info for package name: " + context.getPackageName(), e);
+ currentVersionCode = 0;
+ return;
+ }
+ final int oldVersionCode = getStoredVersionCode();
+ Log.d(TAG, "old: " + oldVersionCode + ", current: " + currentVersionCode);
+ if(oldVersionCode < currentVersionCode) {
+ onUpgrade(oldVersionCode, currentVersionCode);
+ setCurrentVersionCode();
+ }
+ }
+
+ public static int getStoredVersionCode() {
+ return prefs.getInt(KEY_VERSION_CODE, -1);
+ }
+
+ public static void setCurrentVersionCode() {
+ prefs.edit().putInt(KEY_VERSION_CODE, currentVersionCode).apply();
+ }
+
+ private static void onUpgrade(final int oldVersionCode, final int newVersionCode) {
+ if(oldVersionCode < 1030099) {
+ // delete the now obsolete image cache
+ // from now on, Glide will handle caching images
+ new Thread() {
+ public void run() {
+ List<Feed> feeds = DBReader.getFeedList();
+ for (Feed podcast : feeds) {
+ List<FeedItem> episodes = DBReader.getFeedItemList(podcast);
+ for (FeedItem episode : episodes) {
+ FeedImage image = episode.getImage();
+ if (image != null && image.isDownloaded() && image.getFile_url() != null) {
+ File imageFile = new File(image.getFile_url());
+ if (imageFile.exists()) {
+ imageFile.delete();
+ }
+ image.setFile_url(null); // calls setDownloaded(false)
+ DBWriter.setFeedImage(image);
+ }
+ }
+ }
+ }
+ }.start();
+ }
+ if(oldVersionCode < 1050004) {
+ if(MediaPlayer.isPrestoLibraryInstalled(context) && Build.VERSION.SDK_INT >= 16) {
+ UserPreferences.enableSonic(true);
+ }
+ }
+ }
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java
index ac032fcc0..c0ec8d08a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java
@@ -17,6 +17,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicInteger;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.ClientConfig;
@@ -46,8 +47,8 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke
public static enum ExitCode {EXIT_NORMAL, NO_TOKEN, NO_NETWORK, NO_THINGS}
- private volatile int countFailed = 0;
- private volatile int countSuccess = 0;
+ private final AtomicInteger countFailed = new AtomicInteger();
+ private final AtomicInteger countSuccess = new AtomicInteger();
private volatile FlattrThing extraFlattrThing;
@@ -114,12 +115,12 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke
FlattrUtils.clickUrl(context, thing.getPaymentLink());
thing.getFlattrStatus().setFlattred();
publishProgress(R.string.flattr_click_success);
- countSuccess++;
+ countSuccess.incrementAndGet();
} catch (FlattrException e) {
e.printStackTrace();
- countFailed++;
- if (countFailed == 1) {
+ int failed = countFailed.incrementAndGet();
+ if (failed == 1) {
exception = e;
}
}
@@ -148,7 +149,7 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke
super.onPostExecute(exitCode);
switch (exitCode) {
case EXIT_NORMAL:
- if (countFailed > 0) {
+ if (countFailed.get() > 0) {
postFlattrFailedNotification();
}
break;
@@ -190,7 +191,8 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke
}
private void postFlattrFailedNotification() {
- if (countFailed == 0) {
+ int failed = countFailed.get();
+ if (failed == 0) {
return;
}
@@ -198,15 +200,15 @@ public class FlattrClickWorker extends AsyncTask<Void, Integer, FlattrClickWorke
String title;
String subtext;
- if (countFailed == 1) {
+ if (failed == 1) {
title = context.getString(R.string.flattrd_failed_label);
String exceptionMsg = (exception.getMessage() != null) ? exception.getMessage() : "";
subtext = context.getString(R.string.flattr_click_failure, extraFlattrThing.getTitle())
+ "\n" + exceptionMsg;
} else {
title = context.getString(R.string.flattrd_label);
- subtext = context.getString(R.string.flattr_click_success_count, countSuccess) + "\n"
- + context.getString(R.string.flattr_click_failure_count, countFailed);
+ subtext = context.getString(R.string.flattr_click_success_count, countSuccess.get()) + "\n"
+ + context.getString(R.string.flattr_click_failure_count, failed);
}
Notification notification = new NotificationCompat.Builder(context)
diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java
index 2d174a6bc..01c888d6b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java
@@ -63,10 +63,10 @@ public class GpodnetEpisodeAction {
Action action = Action.valueOf(fields[3]);
GpodnetEpisodeAction result = new Builder(podcast, episode, action)
.deviceId(deviceId)
- .timestamp(new Date(Long.valueOf(fields[4])))
- .started(Integer.valueOf(fields[5]))
- .position(Integer.valueOf(fields[6]))
- .total(Integer.valueOf(fields[7]))
+ .timestamp(new Date(Long.parseLong(fields[4])))
+ .started(Integer.parseInt(fields[5]))
+ .position(Integer.parseInt(fields[6]))
+ .total(Integer.parseInt(fields[7]))
.build();
return result;
} catch(IllegalArgumentException e) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
index 6c0aff15e..f9613cc3d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
@@ -17,6 +17,7 @@ import org.json.JSONException;
import java.io.File;
import java.io.IOException;
+import java.net.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -25,10 +26,12 @@ import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver;
+import de.danoeh.antennapod.core.service.download.ProxyConfig;
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
+import de.danoeh.antennapod.core.util.Converter;
/**
* Provides access to preferences set by the user in the settings screen. A
@@ -78,6 +81,11 @@ public class UserPreferences {
public static final String PREF_ENABLE_AUTODL_ON_BATTERY = "prefEnableAutoDownloadOnBattery";
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
public static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
+ public static final String PREF_PROXY_TYPE = "prefProxyType";
+ public static final String PREF_PROXY_HOST = "prefProxyHost";
+ public static final String PREF_PROXY_PORT = "prefProxyPort";
+ public static final String PREF_PROXY_USER = "prefProxyUser";
+ public static final String PREF_PROXY_PASSWORD = "prefProxyPassword";
// Services
public static final String PREF_AUTO_FLATTR = "pref_auto_flattr";
@@ -158,12 +166,12 @@ public class UserPreferences {
public static int getFeedOrder() {
String value = prefs.getString(PREF_DRAWER_FEED_ORDER, "0");
- return Integer.valueOf(value);
+ return Integer.parseInt(value);
}
public static int getFeedCounterSetting() {
String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "0");
- return Integer.valueOf(value);
+ return Integer.parseInt(value);
}
/**
@@ -243,7 +251,7 @@ public class UserPreferences {
}
public static int getSmartMarkAsPlayedSecs() {
- return Integer.valueOf(prefs.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
+ return Integer.parseInt(prefs.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
}
public static boolean isAutoFlattr() {
@@ -260,20 +268,20 @@ public class UserPreferences {
public static float getLeftVolume() {
int volume = prefs.getInt(PREF_LEFT_VOLUME, 100);
- if(volume == 100) {
- return 1.0f;
- } else {
- return (float) (1 - (Math.log(100 - volume) / Math.log(100)));
- }
+ return Converter.getVolumeFromPercentage(volume);
}
public static float getRightVolume() {
int volume = prefs.getInt(PREF_RIGHT_VOLUME, 100);
- if(volume == 100) {
- return 1.0f;
- } else {
- return (float) (1 - (Math.log(100 - volume) / Math.log(100)));
- }
+ return Converter.getVolumeFromPercentage(volume);
+ }
+
+ public static int getLeftVolumePercentage() {
+ return prefs.getInt(PREF_LEFT_VOLUME, 100);
+ }
+
+ public static int getRightVolumePercentage() {
+ return prefs.getInt(PREF_RIGHT_VOLUME, 100);
}
public static boolean shouldPauseForFocusLoss() {
@@ -295,8 +303,8 @@ public class UserPreferences {
String datetime = prefs.getString(PREF_UPDATE_INTERVAL, "");
if(datetime.length() >= 3 && datetime.contains(":")) {
String[] parts = datetime.split(":");
- int hourOfDay = Integer.valueOf(parts[0]);
- int minute = Integer.valueOf(parts[1]);
+ int hourOfDay = Integer.parseInt(parts[0]);
+ int minute = Integer.parseInt(parts[1]);
return new int[] { hourOfDay, minute };
} else {
return new int[0];
@@ -308,7 +316,7 @@ public class UserPreferences {
}
public static int getParallelDownloads() {
- return Integer.valueOf(prefs.getString(PREF_PARALLEL_DOWNLOADS, "4"));
+ return Integer.parseInt(prefs.getString(PREF_PARALLEL_DOWNLOADS, "4"));
}
public static int getEpisodeCacheSizeUnlimited() {
@@ -338,12 +346,12 @@ public class UserPreferences {
public static int getImageCacheSize() {
String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE);
- int cacheSizeInt = Integer.valueOf(cacheSizeString);
+ int cacheSizeInt = Integer.parseInt(cacheSizeString);
// if the cache size is too small the user won't get any images at all
// that's bad, force it back to the default.
if (cacheSizeInt < IMAGE_CACHE_SIZE_MINIMUM) {
prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).apply();
- cacheSizeInt = Integer.valueOf(IMAGE_CACHE_DEFAULT_VALUE);
+ cacheSizeInt = Integer.parseInt(IMAGE_CACHE_DEFAULT_VALUE);
}
int cacheSizeMB = cacheSizeInt * 1024 * 1024;
return cacheSizeMB;
@@ -371,6 +379,42 @@ public class UserPreferences {
return TextUtils.split(selectedNetWorks, ",");
}
+ public static void setProxyConfig(ProxyConfig config) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(PREF_PROXY_TYPE, config.type.name());
+ if(TextUtils.isEmpty(config.host)) {
+ editor.remove(PREF_PROXY_HOST);
+ } else {
+ editor.putString(PREF_PROXY_HOST, config.host);
+ }
+ if(config.port <= 0 || config.port > 65535) {
+ editor.remove(PREF_PROXY_PORT);
+ } else {
+ editor.putInt(PREF_PROXY_PORT, config.port);
+ }
+ if(TextUtils.isEmpty(config.username)) {
+ editor.remove(PREF_PROXY_USER);
+ } else {
+ editor.putString(PREF_PROXY_USER, config.username);
+ }
+ if(TextUtils.isEmpty(config.password)) {
+ editor.remove(PREF_PROXY_PASSWORD);
+ } else {
+ editor.putString(PREF_PROXY_PASSWORD, config.password);
+ }
+ editor.apply();
+ }
+
+ public static ProxyConfig getProxyConfig() {
+ Proxy.Type type = Proxy.Type.valueOf(prefs.getString(PREF_PROXY_TYPE, Proxy.Type.DIRECT.name()));
+ String host = prefs.getString(PREF_PROXY_HOST, null);
+ int port = prefs.getInt(PREF_PROXY_PORT, 0);
+ String username = prefs.getString(PREF_PROXY_USER, null);
+ String password = prefs.getString(PREF_PROXY_PASSWORD, null);
+ ProxyConfig config = new ProxyConfig(type, host, port, username, password);
+ return config;
+ }
+
public static boolean shouldResumeAfterCall() {
return prefs.getBoolean(PREF_RESUME_AFTER_CALL, true);
}
@@ -494,7 +538,7 @@ public class UserPreferences {
if (valueFromPrefs.equals(context.getString(R.string.pref_episode_cache_unlimited))) {
return EPISODE_CACHE_SIZE_UNLIMITED;
} else {
- return Integer.valueOf(valueFromPrefs);
+ return Integer.parseInt(valueFromPrefs);
}
}
@@ -502,15 +546,7 @@ public class UserPreferences {
String[] selectedSpeeds = null;
// If this preference hasn't been set yet, return the default options
if (valueFromPrefs == null) {
- String[] allSpeeds = context.getResources().getStringArray(R.array.playback_speed_values);
- List<String> speedList = new ArrayList<>();
- for (String speedStr : allSpeeds) {
- float speed = Float.parseFloat(speedStr);
- if (speed < 2.0001 && speed * 10 % 1 == 0) {
- speedList.add(speedStr);
- }
- }
- selectedSpeeds = speedList.toArray(new String[speedList.size()]);
+ selectedSpeeds = new String[] { "1.00", "1.25", "1.50", "1.75", "2.00" };
} else {
try {
JSONArray jsonArray = new JSONArray(valueFromPrefs);
@@ -548,7 +584,7 @@ public class UserPreferences {
public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() {
- int cleanupValue = Integer.valueOf(prefs.getString(PREF_EPISODE_CLEANUP, "-1"));
+ int cleanupValue = Integer.parseInt(prefs.getString(PREF_EPISODE_CLEANUP, "-1"));
if (cleanupValue == EPISODE_CLEANUP_QUEUE) {
return new APQueueCleanupAlgorithm();
} else if (cleanupValue == EPISODE_CLEANUP_NULL) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java
index ce5004a98..33c15883b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java
@@ -6,7 +6,7 @@ import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
-import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.preferences.UserPreferences;
/** Listens for events that make it necessary to reset the update alarm. */
@@ -22,8 +22,7 @@ public class AlarmUpdateReceiver extends BroadcastReceiver {
} else if (TextUtils.equals(intent.getAction(), Intent.ACTION_PACKAGE_REPLACED)) {
Log.d(TAG, "Resetting update alarm after app upgrade");
}
- PlaybackPreferences.init(context);
- UserPreferences.init(context);
+ ClientConfig.initialize(context);
UserPreferences.restartUpdateAlarm(false);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
index b959c7301..e0abe0efb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java
@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.util.Log;
+import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.util.NetworkUtils;
@@ -19,6 +20,7 @@ public class FeedUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received intent");
+ ClientConfig.initialize(context);
if (NetworkUtils.isDownloadAllowed()) {
DBTasks.refreshAllFeeds(context, null);
} else {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/MediaButtonReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/MediaButtonReceiver.java
index a900248d2..51cc52e10 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/receiver/MediaButtonReceiver.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/MediaButtonReceiver.java
@@ -5,7 +5,8 @@ import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.KeyEvent;
-import de.danoeh.antennapod.core.BuildConfig;
+
+import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
/** Receives media button events. */
@@ -17,10 +18,10 @@ public class MediaButtonReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Received intent");
- KeyEvent event = (KeyEvent) intent.getExtras().get(
- Intent.EXTRA_KEY_EVENT);
+ Log.d(TAG, "Received intent");
+ KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ ClientConfig.initialize(context);
Intent serviceIntent = new Intent(context, PlaybackService.class);
int keycode = event.getKeyCode();
serviceIntent.putExtra(EXTRA_KEYCODE, keycode);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
index b23819ef7..5dd1e2dfa 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
@@ -2,8 +2,10 @@ package de.danoeh.antennapod.core.service.download;
import android.os.Build;
import android.support.annotation.NonNull;
+import android.text.TextUtils;
import android.util.Log;
+import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
@@ -14,7 +16,10 @@ import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.HttpURLConnection;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
import java.net.Socket;
+import java.net.SocketAddress;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.concurrent.TimeUnit;
@@ -23,6 +28,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBWriter;
/**
@@ -44,12 +50,15 @@ public class AntennapodHttpClient {
*/
public static synchronized OkHttpClient getHttpClient() {
if (httpClient == null) {
-
httpClient = newHttpClient();
}
return httpClient;
}
+ public static synchronized void reinit() {
+ httpClient = newHttpClient();
+ }
+
/**
* Creates a new HTTP client. Most users should just use
* getHttpClient() to get the standard AntennaPod client,
@@ -69,13 +78,13 @@ public class AntennapodHttpClient {
client.networkInterceptors().add(chain -> {
Request request = chain.request();
Response response = chain.proceed(request);
- if(response.code() == HttpURLConnection.HTTP_MOVED_PERM ||
+ if (response.code() == HttpURLConnection.HTTP_MOVED_PERM ||
response.code() == StatusLine.HTTP_PERM_REDIRECT) {
String location = response.header("Location");
- if(location.startsWith("/")) { // URL is not absolute, but relative
+ if (location.startsWith("/")) { // URL is not absolute, but relative
URL url = request.url();
location = url.getProtocol() + "://" + url.getHost() + location;
- } else if(!location.toLowerCase().startsWith("http://") &&
+ } else if (!location.toLowerCase().startsWith("http://") &&
!location.toLowerCase().startsWith("https://")) {
// Reference is relative to current path
URL url = request.url();
@@ -106,6 +115,21 @@ public class AntennapodHttpClient {
client.setFollowRedirects(true);
client.setFollowSslRedirects(true);
+ ProxyConfig config = UserPreferences.getProxyConfig();
+ if (config.type != Proxy.Type.DIRECT) {
+ int port = config.port > 0 ? config.port : ProxyConfig.DEFAULT_PORT;
+ SocketAddress address = InetSocketAddress.createUnresolved(config.host, port);
+ Proxy proxy = new Proxy(config.type, address);
+ client.setProxy(proxy);
+ if (!TextUtils.isEmpty(config.username)) {
+ String credentials = Credentials.basic(config.username, config.password);
+ client.interceptors().add(chain -> {
+ Request request = chain.request().newBuilder()
+ .header("Proxy-Authorization", credentials).build();
+ return chain.proceed(request);
+ });
+ }
+ }
if(16 <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 21) {
client.setSslSocketFactory(new CustomSslSocketFactory());
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
index 7f40ea6e2..de91916a9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java
@@ -128,7 +128,8 @@ public class DownloadRequest implements Parcelable {
DownloadRequest that = (DownloadRequest) o;
- if (lastModified != that.lastModified) return false;
+ if (lastModified != null ? !lastModified.equals(that.lastModified) : that.lastModified != null)
+ return false;
if (deleteOnFailure != that.deleteOnFailure) return false;
if (feedfileId != that.feedfileId) return false;
if (feedfileType != that.feedfileType) return false;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
index 090c48ca0..be6cd88cb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
@@ -188,7 +188,7 @@ public class DownloadService extends Service {
if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
postAuthenticationNotification(downloader.getDownloadRequest());
} else if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR
- && Integer.valueOf(status.getReasonDetailed()) == 416) {
+ && Integer.parseInt(status.getReasonDetailed()) == 416) {
Log.d(TAG, "Requested invalid range, restarting download from the beginning");
FileUtils.deleteQuietly(new File(downloader.getDownloadRequest().getDestination()));
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
index e3a195253..2b26f58c0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
@@ -27,6 +27,7 @@ import java.util.Date;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.feed.FeedImage;
+import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.StorageUtils;
@@ -67,6 +68,12 @@ public class HttpDownloader extends Downloader {
final URI uri = URIUtil.getURIFromRequestUrl(request.getSource());
Request.Builder httpReq = new Request.Builder().url(uri.toURL())
.header("User-Agent", ClientConfig.USER_AGENT);
+ if(request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
+ // set header explicitly so that okhttp doesn't do transparent gzip
+ Log.d(TAG, "addHeader(\"Accept-Encoding\", \"identity\")");
+ httpReq.addHeader("Accept-Encoding", "identity");
+ }
+
if(!TextUtils.isEmpty(request.getLastModified())) {
String lastModified = request.getLastModified();
Date lastModifiedDate = DateUtils.parse(lastModified);
@@ -117,6 +124,15 @@ public class HttpDownloader extends Downloader {
throw e;
}
}
+
+ if(request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
+ String contentType = response.header("Content-Type");
+ if(!contentType.startsWith("audio/") && !contentType.startsWith("video/")) {
+ onFail(DownloadError.ERROR_FILE_TYPE, null);
+ return;
+ }
+ }
+
responseBody = response.body();
String contentEncodingHeader = response.header("Content-Encoding");
boolean isGzip = false;
@@ -180,7 +196,7 @@ public class HttpDownloader extends Downloader {
&& !TextUtils.isEmpty(contentRangeHeader)) {
String start = contentRangeHeader.substring("bytes ".length(),
contentRangeHeader.indexOf("-"));
- request.setSoFar(Long.valueOf(start));
+ request.setSoFar(Long.parseLong(start));
Log.d(TAG, "Starting download at position " + request.getSoFar());
out = new RandomAccessFile(destination, "rw");
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java
new file mode 100644
index 000000000..e886932f2
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/ProxyConfig.java
@@ -0,0 +1,32 @@
+package de.danoeh.antennapod.core.service.download;
+
+import android.support.annotation.Nullable;
+
+import java.net.Proxy;
+
+public class ProxyConfig {
+
+ public final Proxy.Type type;
+ @Nullable public final String host;
+ @Nullable public final int port;
+ @Nullable public final String username;
+ @Nullable public final String password;
+
+ public final static int DEFAULT_PORT = 8080;
+
+ public static ProxyConfig direct() {
+ return new ProxyConfig(Proxy.Type.DIRECT, null, 0, null, null);
+ }
+
+ public static ProxyConfig http(String host, int port, String username, String password) {
+ return new ProxyConfig(Proxy.Type.HTTP, host, port, username, password);
+ }
+
+ public ProxyConfig(Proxy.Type type, String host, int port, String username, String password) {
+ this.type = type;
+ this.host = host;
+ this.port = port;
+ this.username = username;
+ this.password = password;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
index a82e82506..775820d7d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
@@ -604,7 +604,11 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre
* Returns the position of the current media object or INVALID_TIME if the position could not be retrieved.
*/
public int getPosition() {
- if (!playerLock.tryLock()) {
+ try {
+ if (!playerLock.tryLock(50, TimeUnit.MILLISECONDS)) {
+ return INVALID_TIME;
+ }
+ } catch (InterruptedException e) {
return INVALID_TIME;
}
@@ -693,7 +697,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre
}
/**
- * Sets the playback speed.
+ * Sets the playback volume.
* This method is executed on an internal executor service.
*/
public void setVolume(final float volumeLeft, float volumeRight) {
@@ -701,7 +705,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre
}
/**
- * Sets the playback speed.
+ * Sets the playback volume.
* This method is executed on the caller's thread.
*/
private void setVolumeSync(float volumeLeft, float volumeRight) {
@@ -946,15 +950,16 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre
if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now
resume();
} else { // we ducked => raise audio level back
- audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
- AudioManager.ADJUST_RAISE, 0);
+ setVolumeSync(UserPreferences.getLeftVolume(),
+ UserPreferences.getRightVolume());
}
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
if (playerStatus == PlayerStatus.PLAYING) {
if (!UserPreferences.shouldPauseForFocusLoss()) {
Log.d(TAG, "Lost audio focus temporarily. Ducking...");
- audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
- AudioManager.ADJUST_LOWER, 0);
+ final float DUCK_FACTOR = 0.25f;
+ setVolumeSync(DUCK_FACTOR * UserPreferences.getLeftVolume(),
+ DUCK_FACTOR * UserPreferences.getRightVolume());
pausedBecauseOfTransientAudiofocusLoss = false;
} else {
Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing...");
@@ -1205,6 +1210,71 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre
private static final String TAG = "MediaSessionCompat";
@Override
+ public void onPlay() {
+ Log.d(TAG, "onPlay()");
+ if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) {
+ resume();
+ } else if (playerStatus == PlayerStatus.INITIALIZED) {
+ setStartWhenPrepared(true);
+ prepare();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ Log.d(TAG, "onPause()");
+ if (playerStatus == PlayerStatus.PLAYING) {
+ pause(false, true);
+ }
+ if (UserPreferences.isPersistNotify()) {
+ pause(false, true);
+ } else {
+ pause(true, true);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ Log.d(TAG, "onStop()");
+ stop();
+ }
+
+ @Override
+ public void onSkipToPrevious() {
+ Log.d(TAG, "onSkipToPrevious()");
+ seekDelta(-UserPreferences.getRewindSecs() * 1000);
+ }
+
+ @Override
+ public void onRewind() {
+ Log.d(TAG, "onRewind()");
+ seekDelta(-UserPreferences.getRewindSecs() * 1000);
+ }
+
+ @Override
+ public void onFastForward() {
+ Log.d(TAG, "onFastForward()");
+ seekDelta(UserPreferences.getFastFowardSecs() * 1000);
+ }
+
+ @Override
+ public void onSkipToNext() {
+ Log.d(TAG, "onSkipToNext()");
+ if(UserPreferences.shouldHardwareButtonSkip()) {
+ endPlayback(true);
+ } else {
+ seekDelta(UserPreferences.getFastFowardSecs() * 1000);
+ }
+ }
+
+
+ @Override
+ public void onSeekTo(long pos) {
+ Log.d(TAG, "onSeekTo()");
+ seekTo((int) pos);
+ }
+
+ @Override
public boolean onMediaButtonEvent(final Intent mediaButton) {
Log.d(TAG, "onMediaButtonEvent(" + mediaButton + ")");
if (mediaButton != null) {
@@ -1240,42 +1310,27 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre
return true;
}
case KeyEvent.KEYCODE_MEDIA_PLAY: {
- Log.d(TAG, "Received Play event from RemoteControlClient");
- if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) {
- resume();
- } else if (playerStatus == PlayerStatus.INITIALIZED) {
- setStartWhenPrepared(true);
- prepare();
- }
+ sessionCallback.onPlay();
return true;
}
case KeyEvent.KEYCODE_MEDIA_PAUSE: {
- Log.d(TAG, "Received Pause event from RemoteControlClient");
- if (playerStatus == PlayerStatus.PLAYING) {
- pause(false, true);
- }
- if (UserPreferences.isPersistNotify()) {
- pause(false, true);
- } else {
- pause(true, true);
- }
+ sessionCallback.onPause();
return true;
}
case KeyEvent.KEYCODE_MEDIA_STOP: {
- Log.d(TAG, "Received Stop event from RemoteControlClient");
- stop();
+ sessionCallback.onStop();
return true;
}
case KeyEvent.KEYCODE_MEDIA_PREVIOUS: {
- seekDelta(-UserPreferences.getRewindSecs() * 1000);
+ sessionCallback.onSkipToPrevious();
return true;
}
case KeyEvent.KEYCODE_MEDIA_REWIND: {
- seekDelta(-UserPreferences.getRewindSecs() * 1000);
+ sessionCallback.onRewind();
return true;
}
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
- seekDelta(UserPreferences.getFastFowardSecs() * 1000);
+ sessionCallback.onFastForward();
return true;
}
case KeyEvent.KEYCODE_MEDIA_NEXT: {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
index 61a07ae2d..e69e1887d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
@@ -4,6 +4,7 @@ import android.database.Cursor;
import android.support.v4.util.ArrayMap;
import android.util.Log;
+import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -677,7 +678,7 @@ public final class DBReader {
* as well as chapter marks of the FeedItems will also be loaded from the database.
*/
public static List<FeedItem> getFeedItems(final long... itemIds) {
- Log.d(TAG, "getFeedItems() called with: " + "itemIds = [" + itemIds + "]");
+ Log.d(TAG, "getFeedItems() called with: " + "itemIds = [" + Arrays.toString(itemIds) + "]");
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
List<FeedItem> items = getFeedItems(adapter, itemIds);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
index 99c4cd67a..769a796e3 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
@@ -60,12 +60,12 @@ public class NSITunes extends Namespace {
try {
int duration = 0;
if (parts.length == 2) {
- duration += TimeUnit.MINUTES.toMillis(Long.valueOf(parts[0])) +
- TimeUnit.SECONDS.toMillis(Long.valueOf(parts[1]));
+ duration += TimeUnit.MINUTES.toMillis(Long.parseLong(parts[0])) +
+ TimeUnit.SECONDS.toMillis(Long.parseLong(parts[1]));
} else if (parts.length >= 3) {
- duration += TimeUnit.HOURS.toMillis(Long.valueOf(parts[0])) +
- TimeUnit.MINUTES.toMillis(Long.valueOf(parts[1])) +
- TimeUnit.SECONDS.toMillis(Long.valueOf(parts[2]));
+ duration += TimeUnit.HOURS.toMillis(Long.parseLong(parts[0])) +
+ TimeUnit.MINUTES.toMillis(Long.parseLong(parts[1])) +
+ TimeUnit.SECONDS.toMillis(Long.parseLong(parts[2]));
} else {
return;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java
index 1b929b214..5b046d7a7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java
@@ -88,9 +88,9 @@ public final class Converter {
if (parts.length != 3) {
return 0;
}
- return Integer.valueOf(parts[0]) * 3600 * 1000 +
- Integer.valueOf(parts[1]) * 60 * 1000 +
- Integer.valueOf(parts[2]) * 1000;
+ return Integer.parseInt(parts[0]) * 3600 * 1000 +
+ Integer.parseInt(parts[1]) * 60 * 1000 +
+ Integer.parseInt(parts[2]) * 1000;
}
/** Converts short duration string (HH:MM) to milliseconds. */
@@ -99,8 +99,8 @@ public final class Converter {
if (parts.length != 2) {
return 0;
}
- return Integer.valueOf(parts[0]) * 3600 * 1000 +
- Integer.valueOf(parts[1]) * 1000 * 60;
+ return Integer.parseInt(parts[0]) * 3600 * 1000 +
+ Integer.parseInt(parts[1]) * 1000 * 60;
}
/** Converts milliseconds to a localized string containing hours and minutes */
@@ -118,5 +118,16 @@ public final class Converter {
result += minutes;
return result;
}
-
+
+ /**
+ * Converts the volume as read as the progress from a SeekBar scaled to 100 and as saved in
+ * UserPreferences to the format taken by setVolume methods.
+ * @param progress integer between 0 to 100 taken from the SeekBar progress
+ * @return the appropriate volume as float taken by setVolume methods
+ */
+ public static float getVolumeFromPercentage(int progress){
+ if (progress==100)
+ return 1f;
+ return (float) (1 - (Math.log(101 - progress) / Math.log(101)));
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
index 6b0f423df..314062e52 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
@@ -19,14 +19,8 @@ public class DateUtils {
private static final String TAG = "DateUtils";
- private static final SimpleDateFormat parser = new SimpleDateFormat("", Locale.US);
private static final TimeZone defaultTimezone = TimeZone.getTimeZone("GMT");
- static {
- parser.setLenient(false);
- parser.setTimeZone(defaultTimezone);
- }
-
public static Date parse(final String input) {
if(input == null) {
throw new IllegalArgumentException("Date must not be null");
@@ -86,6 +80,10 @@ public class DateUtils {
"yyyy-MM-dd"
};
+ SimpleDateFormat parser = new SimpleDateFormat("", Locale.US);
+ parser.setLenient(false);
+ parser.setTimeZone(defaultTimezone);
+
ParsePosition pos = new ParsePosition(0);
for(String pattern : patterns) {
parser.applyPattern(pattern);
@@ -117,13 +115,13 @@ public class DateUtils {
int idx = 0;
if (parts.length == 3) {
// string has hours
- result += Integer.valueOf(parts[idx]) * 3600000L;
+ result += Integer.parseInt(parts[idx]) * 3600000L;
idx++;
}
if (parts.length >= 2) {
- result += Integer.valueOf(parts[idx]) * 60000L;
+ result += Integer.parseInt(parts[idx]) * 60000L;
idx++;
- result += (Float.valueOf(parts[idx])) * 1000L;
+ result += (Float.parseFloat(parts[idx])) * 1000L;
}
return result;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java
index 602c221bf..d3f6c6b79 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java
@@ -19,7 +19,8 @@ public enum DownloadError {
ERROR_UNKNOWN_HOST(11, R.string.download_error_unknown_host),
ERROR_REQUEST_ERROR(12, R.string.download_error_request_error),
ERROR_DB_ACCESS_ERROR(13, R.string.download_error_db_access),
- ERROR_UNAUTHORIZED(14, R.string.download_error_unauthorized);
+ ERROR_UNAUTHORIZED(14, R.string.download_error_unauthorized),
+ ERROR_FILE_TYPE(15, R.string.download_error_file_type_type);
private final int code;
private final int resId;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/IntList.java b/core/src/main/java/de/danoeh/antennapod/core/util/IntList.java
index 673c81235..1cbe7fade 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/IntList.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/IntList.java
@@ -35,7 +35,7 @@ public final class IntList {
int hashCode = 1;
for (int i = 0; i < size; i++) {
int value = values[i];
- hashCode = 31 * hashCode + (int)(value ^ (value >>> 32));
+ hashCode = 31 * hashCode + value;
}
return hashCode;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/gui/FeedItemUndoToken.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/FeedItemUndoToken.java
deleted file mode 100644
index 17581d3e9..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/gui/FeedItemUndoToken.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package de.danoeh.antennapod.core.util.gui;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import de.danoeh.antennapod.core.feed.FeedItem;
-
-/**
- * Used by an UndoBarController for saving a removed FeedItem
- */
-public class FeedItemUndoToken implements Parcelable {
- private long itemId;
- private long feedId;
- private int position;
-
- public FeedItemUndoToken(FeedItem item, int position) {
- this.itemId = item.getId();
- this.feedId = item.getFeed().getId();
- this.position = position;
- }
-
- private FeedItemUndoToken(Parcel in) {
- itemId = in.readLong();
- feedId = in.readLong();
- position = in.readInt();
- }
-
- public static final Parcelable.Creator<FeedItemUndoToken> CREATOR = new Parcelable.Creator<FeedItemUndoToken>() {
- public FeedItemUndoToken createFromParcel(Parcel in) {
- return new FeedItemUndoToken(in);
- }
-
- public FeedItemUndoToken[] newArray(int size) {
- return new FeedItemUndoToken[size];
- }
- };
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(itemId);
- out.writeLong(feedId);
- out.writeInt(position);
- }
-
- public long getFeedItemId() {
- return itemId;
- }
-
- public int getPosition() {
- return position;
- }
-}
-
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
index 27935978c..1a011a90b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
@@ -19,7 +19,6 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.SurfaceHolder;
-import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
@@ -424,6 +423,7 @@ public abstract class PlaybackController {
clearStatusMsg();
checkMediaInfoLoaded();
cancelPositionObserver();
+ onPositionObserverUpdate();
updatePlayButtonAppearance(playResource, playText);
if (PlaybackService.getCurrentMediaType() == MediaType.VIDEO) {
setScreenOn(false);
@@ -574,34 +574,32 @@ public abstract class PlaybackController {
}
- public OnClickListener newOnPlayButtonClickListener() {
- return v -> {
- if (playbackService == null) {
- Log.w(TAG, "Play/Pause button was pressed, but playbackservice was null!");
- return;
- }
- switch (status) {
- case PLAYING:
- playbackService.pause(true, reinitOnPause);
- break;
- case PAUSED:
- case PREPARED:
- playbackService.resume();
- break;
- case PREPARING:
- playbackService.setStartWhenPrepared(!playbackService
- .isStartWhenPrepared());
- if (reinitOnPause
- && playbackService.isStartWhenPrepared() == false) {
- playbackService.reinit();
- }
- break;
- case INITIALIZED:
- playbackService.setStartWhenPrepared(true);
- playbackService.prepare();
- break;
- }
- };
+ public void playPause() {
+ if (playbackService == null) {
+ Log.w(TAG, "Play/Pause button was pressed, but playbackservice was null!");
+ return;
+ }
+ switch (status) {
+ case PLAYING:
+ playbackService.pause(true, reinitOnPause);
+ break;
+ case PAUSED:
+ case PREPARED:
+ playbackService.resume();
+ break;
+ case PREPARING:
+ playbackService.setStartWhenPrepared(!playbackService
+ .isStartWhenPrepared());
+ if (reinitOnPause
+ && playbackService.isStartWhenPrepared() == false) {
+ playbackService.reinit();
+ }
+ break;
+ case INITIALIZED:
+ playbackService.setStartWhenPrepared(true);
+ playbackService.prepare();
+ break;
+ }
}
public boolean serviceAvailable() {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java
index 2eee1ac87..8d9151396 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java
@@ -2,7 +2,10 @@ package de.danoeh.antennapod.core.util.playback;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
@@ -14,6 +17,7 @@ import org.jsoup.select.Elements;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.ShownotesProvider;
@@ -32,26 +36,32 @@ public class Timeline {
private ShownotesProvider shownotesProvider;
-
- private final String colorString;
+ private final String noShownotesLabel;
+ private final String colorPrimaryString;
+ private final String colorSecondaryString;
private final int pageMargin;
public Timeline(Context context, ShownotesProvider shownotesProvider) {
if (shownotesProvider == null) throw new IllegalArgumentException("shownotesProvider = null");
this.shownotesProvider = shownotesProvider;
- TypedArray res = context
- .getTheme()
- .obtainStyledAttributes(
- new int[]{android.R.attr.textColorPrimary});
- int colorResource = res.getColor(0, 0);
- colorString = String.format("#%06X",
- 0xFFFFFF & colorResource);
+ noShownotesLabel = context.getString(R.string.no_shownotes_label);
+
+ TypedArray res = context.getTheme().obtainStyledAttributes(
+ new int[]{ android.R.attr.textColorPrimary});
+ @ColorInt int col = res.getColor(0, 0);
+ colorPrimaryString = "rgba(" + Color.red(col) + "," + Color.green(col) + "," +
+ Color.blue(col) + "," + (Color.alpha(col)/256.0) + ")";
+ res.recycle();
+ res = context.getTheme().obtainStyledAttributes(
+ new int[]{android.R.attr.textColorSecondary});
+ col = res.getColor(0, 0);
+ colorSecondaryString = "rgba(" + Color.red(col) + "," + Color.green(col) + "," +
+ Color.blue(col) + "," + (Color.alpha(col)/256.0) + ")";
res.recycle();
- pageMargin = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP, 8, context.getResources()
- .getDisplayMetrics()
+ pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
+ context.getResources().getDisplayMetrics()
);
}
@@ -82,9 +92,24 @@ public class Timeline {
e.printStackTrace();
return null;
}
- if (shownotes == null) {
- Log.d(TAG, "shownotesProvider contained no shownotes. Returning empty string");
- return "";
+
+ if(TextUtils.isEmpty(shownotes)) {
+ Log.d(TAG, "shownotesProvider contained no shownotes. Returning 'no shownotes' message");
+ shownotes ="<html>" +
+ "<head>" +
+ "<style type='text/css'>" +
+ "html, body { margin: 0; padding: 0; width: 100%; height: 100%; } " +
+ "html { display: table; }" +
+ "body { display: table-cell; vertical-align: middle; text-align:center;" +
+ "-webkit-text-size-adjust: none; font-size: 87%; color: " + colorSecondaryString + ";} " +
+ "</style>" +
+ "</head>" +
+ "<body>" +
+ "<p>" + noShownotesLabel + "</p>" +
+ "</body>" +
+ "</html>";
+ Log.d(TAG, "shownotes: " + shownotes);
+ return shownotes;
}
// replace ASCII line breaks with HTML ones if shownotes don't contain HTML line breaks already
@@ -95,7 +120,7 @@ public class Timeline {
Document document = Jsoup.parse(shownotes);
// apply style
- String styleStr = String.format(WEBVIEW_STYLE, colorString, "100%", pageMargin,
+ String styleStr = String.format(WEBVIEW_STYLE, colorPrimaryString, "100%", pageMargin,
pageMargin, pageMargin, pageMargin);
document.head().appendElement("style").attr("type", "text/css").text(styleStr);
@@ -125,8 +150,7 @@ public class Timeline {
element.html(buffer.toString());
}
}
-
- Log.i(TAG, "Out: " + document.toString());
+
return document.toString();
}
@@ -148,7 +172,7 @@ public class Timeline {
try {
if (m.find()) {
- return Integer.valueOf(m.group(1));
+ return Integer.parseInt(m.group(1));
}
} catch (NumberFormatException e) {
e.printStackTrace();