diff options
Diffstat (limited to 'core/src/main/java')
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(); |