diff options
Diffstat (limited to 'core/src/main/java')
20 files changed, 202 insertions, 118 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java index 835dee735..ec10b78aa 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java @@ -2,31 +2,35 @@ package de.danoeh.antennapod.core.glide; import android.content.Context; +import android.support.annotation.NonNull; import com.bumptech.glide.Glide; import com.bumptech.glide.GlideBuilder; +import com.bumptech.glide.Registry; +import com.bumptech.glide.annotation.GlideModule; import com.bumptech.glide.load.DecodeFormat; import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; -import com.bumptech.glide.module.GlideModule; +import com.bumptech.glide.module.AppGlideModule; import java.io.InputStream; +import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.core.preferences.UserPreferences; /** * {@see com.bumptech.glide.integration.okhttp.OkHttpGlideModule} */ -public class ApGlideModule implements GlideModule { +@GlideModule +public class ApGlideModule extends AppGlideModule { @Override - public void applyOptions(Context context, GlideBuilder builder) { - builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); + public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) { + builder.setDefaultRequestOptions(new RequestOptions().format(DecodeFormat.PREFER_ARGB_8888)); builder.setDiskCache(new InternalCacheDiskCacheFactory(context, UserPreferences.getImageCacheSize())); } @Override - public void registerComponents(Context context, Glide glide) { - glide.register(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); + public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { + registry.append(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); } - } diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index 3e4f06a12..bd5276100 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -1,12 +1,12 @@ package de.danoeh.antennapod.core.glide; -import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher; -import com.bumptech.glide.load.data.DataFetcher; -import com.bumptech.glide.load.model.GenericLoaderFactory; +import com.bumptech.glide.load.Options; import com.bumptech.glide.load.model.GlideUrl; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.model.ModelLoaderFactory; @@ -15,6 +15,8 @@ import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import com.bumptech.glide.load.model.MultiModelLoaderFactory; +import com.bumptech.glide.signature.ObjectKey; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; @@ -56,19 +58,20 @@ class ApOkHttpUrlLoader implements ModelLoader<String, InputStream> { /** * Constructor for a new Factory that runs requests using a static singleton client. */ - public Factory() { + Factory() { this(getInternalClient()); } /** * Constructor for a new Factory that runs requests using given client. */ - public Factory(OkHttpClient client) { + Factory(OkHttpClient client) { this.client = client; } + @NonNull @Override - public ModelLoader<String, InputStream> build(Context context, GenericLoaderFactory factories) { + public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) { return new ApOkHttpUrlLoader(client); } @@ -84,20 +87,26 @@ class ApOkHttpUrlLoader implements ModelLoader<String, InputStream> { this.client = client; } + @Nullable @Override - public DataFetcher<InputStream> getResourceFetcher(String model, int width, int height) { - Log.d(TAG, "getResourceFetcher() called with: " + "model = [" + model + "], width = [" + public LoadData<InputStream> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) { + Log.d(TAG, "buildLoadData() called with: " + "model = [" + model + "], width = [" + width + "], height = [" + height + "]"); if(TextUtils.isEmpty(model)) { return null; } else if(model.startsWith("/")) { - return new AudioCoverFetcher(model); + return new LoadData<>(new ObjectKey(model), new AudioCoverFetcher(model)); } else { GlideUrl url = new GlideUrl(model); - return new OkHttpStreamFetcher(client, url); + return new LoadData<>(new ObjectKey(model), new OkHttpStreamFetcher(client, url)); } } + @Override + public boolean handles(@NonNull String s) { + return true; + } + private static class NetworkAllowanceInterceptor implements Interceptor { @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java index 8159a1b3e..479846655 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java @@ -2,7 +2,9 @@ package de.danoeh.antennapod.core.glide; import android.media.MediaMetadataRetriever; +import android.support.annotation.NonNull; import com.bumptech.glide.Priority; +import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.data.DataFetcher; import java.io.ByteArrayInputStream; @@ -20,22 +22,20 @@ class AudioCoverFetcher implements DataFetcher<InputStream> { this.path = path; } - @Override public String getId() { - return path; - } - - @Override public InputStream loadData(Priority priority) throws Exception { + @Override + public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(path); byte[] picture = retriever.getEmbeddedPicture(); if (picture != null) { - return new ByteArrayInputStream(picture); + callback.onDataReady(new ByteArrayInputStream(picture)); + return; } } finally { retriever.release(); } - throw new IOException("Loading embedded cover did not work"); + callback.onLoadFailed(new IOException("Loading embedded cover did not work")); } @Override public void cleanup() { @@ -44,4 +44,16 @@ class AudioCoverFetcher implements DataFetcher<InputStream> { @Override public void cancel() { // cannot cancel } + + @NonNull + @Override + public Class<InputStream> getDataClass() { + return InputStream.class; + } + + @NonNull + @Override + public DataSource getDataSource() { + return DataSource.LOCAL; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java index ee58c2f39..a740782d6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java @@ -1,13 +1,15 @@ package de.danoeh.antennapod.core.glide; -import android.content.Context; import android.graphics.Bitmap; import android.media.ThumbnailUtils; +import android.support.annotation.NonNull; import android.util.Log; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; +import java.security.MessageDigest; + public class FastBlurTransformation extends BitmapTransformation { private static final String TAG = FastBlurTransformation.class.getSimpleName(); @@ -15,8 +17,8 @@ public class FastBlurTransformation extends BitmapTransformation { private static final int STACK_BLUR_RADIUS = 1; private static final int BLUR_IMAGE_WIDTH = 150; - public FastBlurTransformation(Context context) { - super(context); + public FastBlurTransformation() { + super(); } @Override @@ -33,11 +35,6 @@ public class FastBlurTransformation extends BitmapTransformation { return result; } - @Override - public String getId() { - return "FastBlurTransformation[width=" + BLUR_IMAGE_WIDTH + "px,radius=" + STACK_BLUR_RADIUS +"]"; - } - private static Bitmap fastBlur(Bitmap bitmap, int radius) { // Stack Blur v1.0 from @@ -264,4 +261,8 @@ public class FastBlurTransformation extends BitmapTransformation { return bitmap; } + @Override + public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { + messageDigest.update(TAG.getBytes()); + } }
\ No newline at end of file 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 791ecfa1b..9870582c9 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 @@ -104,7 +104,9 @@ public class UserPreferences { // Mediaplayer public static final String PREF_MEDIA_PLAYER = "prefMediaPlayer"; + public static final String PREF_MEDIA_PLAYER_EXOPLAYER = "exoplayer"; private static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed"; + public static final String PREF_PLAYBACK_SKIP_SILENCE = "prefSkipSilence"; private static final String PREF_FAST_FORWARD_SECS = "prefFastForwardSecs"; private static final String PREF_REWIND_SECS = "prefRewindSecs"; private static final String PREF_QUEUE_LOCKED = "prefQueueLocked"; @@ -322,6 +324,10 @@ public class UserPreferences { return prefs.getString(PREF_PLAYBACK_SPEED, "1.00"); } + public static boolean isSkipSilence() { + return prefs.getBoolean(PREF_PLAYBACK_SKIP_SILENCE, false); + } + public static String[] getPlaybackSpeedArray() { return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); } @@ -508,6 +514,12 @@ public class UserPreferences { .apply(); } + public static void setSkipSilence(boolean skipSilence) { + prefs.edit() + .putBoolean(PREF_PLAYBACK_SKIP_SILENCE, skipSilence) + .apply(); + } + public static void setPlaybackSpeedArray(String[] speeds) { JSONArray jsonArray = new JSONArray(); for (String speed : speeds) { @@ -652,7 +664,7 @@ public class UserPreferences { } public static boolean useExoplayer() { - return prefs.getString(PREF_MEDIA_PLAYER, "sonic").equals("exoplayer"); + return prefs.getString(PREF_MEDIA_PLAYER, "sonic").equals(PREF_MEDIA_PLAYER_EXOPLAYER); } public static void enableSonic() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java index e1d87e1d5..281bd064b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java @@ -25,7 +25,6 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.util.Util; import org.antennapod.audio.MediaPlayer; - import de.danoeh.antennapod.core.util.playback.IPlayer; @@ -43,7 +42,7 @@ public class ExoPlayerWrapper implements IPlayer { } private SimpleExoPlayer createPlayer() { - SimpleExoPlayer p = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(mContext), + SimpleExoPlayer p = ExoPlayerFactory.newSimpleInstance(mContext, new DefaultRenderersFactory(mContext), new DefaultTrackSelector(), new DefaultLoadControl()); p.setSeekParameters(SeekParameters.PREVIOUS_SYNC); p.addListener(new Player.EventListener() { @@ -192,9 +191,9 @@ public class ExoPlayerWrapper implements IPlayer { } @Override - public void setPlaybackSpeed(float v) { + public void setPlaybackParams(float speed, boolean skipSilence) { PlaybackParameters params = mExoPlayer.getPlaybackParameters(); - mExoPlayer.setPlaybackParameters(new PlaybackParameters(v, params.pitch)); + mExoPlayer.setPlaybackParameters(new PlaybackParameters(speed, params.pitch, skipSilence)); } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index c7948b157..9274b9a49 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -236,7 +236,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { Log.e(TAG, Log.getStackTraceString(e)); UserPreferences.setPlaybackSpeed(String.valueOf(speed)); } - setSpeed(speed); + setPlaybackParams(speed, UserPreferences.isSkipSilence()); setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume()); if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { @@ -537,14 +537,14 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { * Sets the playback speed. * This method is executed on the caller's thread. */ - private void setSpeedSync(float speed) { + private void setSpeedSyncAndSkipSilence(float speed, boolean skipSilence) { playerLock.lock(); if (media != null && media.getMediaType() == MediaType.AUDIO) { if (mediaPlayer.canSetSpeed()) { - mediaPlayer.setPlaybackSpeed(speed); Log.d(TAG, "Playback speed was set to " + speed); callback.playbackSpeedChanged(speed); } + mediaPlayer.setPlaybackParams(speed, skipSilence); } playerLock.unlock(); } @@ -554,8 +554,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { * This method is executed on an internal executor service. */ @Override - public void setSpeed(final float speed) { - executor.submit(() -> setSpeedSync(speed)); + public void setPlaybackParams(final float speed, final boolean skipSilence) { + executor.submit(() -> setSpeedSyncAndSkipSilence(speed, skipSilence)); } /** @@ -991,7 +991,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private final MediaPlayer.OnErrorListener audioErrorListener = (mp, what, extra) -> { - if(mp.canFallback()) { + if(mp != null && mp.canFallback()) { mp.fallback(); return true; } else { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 68c9ac0ce..66cf7d244 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -39,6 +39,7 @@ import android.view.SurfaceHolder; import android.widget.Toast; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.Target; import java.util.ArrayList; @@ -1165,10 +1166,10 @@ public class PlaybackService extends MediaBrowserServiceCompat { builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, imageLocation); try { Bitmap art = Glide.with(this) - .load(imageLocation) .asBitmap() - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + .load(imageLocation) + .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY)) + .submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) .get(); builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); } catch (Throwable tr) { @@ -1239,11 +1240,11 @@ public class PlaybackService extends MediaBrowserServiceCompat { android.R.dimen.notification_large_icon_width); try { icon = Glide.with(PlaybackService.this) - .load(playable.getImageLocation()) .asBitmap() - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .centerCrop() - .into(iconSize, iconSize) + .load(playable.getImageLocation()) + .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY)) + .apply(new RequestOptions().centerCrop()) + .submit(iconSize, iconSize) .get(); } catch (Throwable tr) { Log.e(TAG, "Error loading the media icon for the notification", tr); @@ -1628,7 +1629,11 @@ public class PlaybackService extends MediaBrowserServiceCompat { } public void setSpeed(float speed) { - mediaPlayer.setSpeed(speed); + mediaPlayer.setPlaybackParams(speed, UserPreferences.isSkipSilence()); + } + + public void skipSilence(boolean skipSilence) { + mediaPlayer.setPlaybackParams(getCurrentPlaybackSpeed(), skipSilence); } public void setVolume(float leftVolume, float rightVolume) { 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 a2481b801..b8198fa63 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 @@ -148,10 +148,12 @@ public abstract class PlaybackServiceMediaPlayer { public abstract boolean canSetSpeed(); /** - * Sets the playback speed. + * Sets the playback parameters. + * - Speed + * - SkipSilence (ExoPlayer only) * This method is executed on an internal executor service. */ - public abstract void setSpeed(float speed); + public abstract void setPlaybackParams(final float speed, final boolean skipSilence); /** * Returns the current playback speed. If the playback speed could not be retrieved, 1 is returned. 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 718459db8..83aa4c780 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 @@ -1,6 +1,7 @@ package de.danoeh.antennapod.core.storage; import android.database.Cursor; +import android.support.annotation.Nullable; import android.support.v4.util.ArrayMap; import android.text.TextUtils; import android.util.Log; @@ -574,6 +575,7 @@ public final class DBReader { } } + @Nullable static Feed getFeed(final long feedId, PodDBAdapter adapter) { Feed feed = null; Cursor cursor = null; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index ba7d4b47b..dab8e19b5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -17,7 +17,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import de.danoeh.antennapod.core.ClientConfig; @@ -28,11 +27,9 @@ import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; -import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.LongList; @@ -207,6 +204,11 @@ public final class DBTasks { }).start(); } + public static long getLastRefreshAllFeedsTimeMillis(final Context context) { + SharedPreferences prefs = context.getSharedPreferences(DBTasks.PREF_NAME, MODE_PRIVATE); + return prefs.getLong(DBTasks.PREF_LAST_REFRESH, 0); + } + /** * @param context * @param feedList the list of feeds to refresh @@ -317,31 +319,6 @@ public final class DBTasks { DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages, force); } - /* - * Checks if the app should refresh all feeds, i.e. if the last auto refresh failed. - * - * The feeds are only refreshed if an update interval or time of day is set and the last - * (successful) refresh was before the last interval or more than a day ago, respectively. - */ - public static void checkShouldRefreshFeeds(Context context) { - long interval = 0; - if(UserPreferences.getUpdateInterval() > 0) { - interval = UserPreferences.getUpdateInterval(); - } else if(UserPreferences.getUpdateTimeOfDay().length > 0){ - interval = TimeUnit.DAYS.toMillis(1); - } - if(interval == 0) { // auto refresh is disabled - return; - } - SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE); - long lastRefresh = prefs.getLong(PREF_LAST_REFRESH, 0); - Log.d(TAG, "last refresh: " + Converter.getDurationStringLocalized(context, - System.currentTimeMillis() - lastRefresh) + " ago"); - if(lastRefresh <= System.currentTimeMillis() - interval) { - DBTasks.refreshAllFeeds(context, null); - } - } - /** * Notifies the database about a missing FeedMedia file. This method will correct the FeedMedia object's values in the * DB and send a FeedUpdateBroadcast. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 4566df2fc..f1410b894 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.storage; +import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; @@ -12,6 +13,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.media.MediaMetadataRetriever; +import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; @@ -326,10 +328,14 @@ public class PodDBAdapter { return this; } + @SuppressLint("NewApi") private SQLiteDatabase openDb() { SQLiteDatabase newDb; try { newDb = SingletonHolder.dbHelper.getWritableDatabase(); + if (Build.VERSION.SDK_INT >= 16) { + newDb.disableWriteAheadLogging(); + } } catch (SQLException ex) { Log.e(TAG, Log.getStackTraceString(ex)); newDb = SingletonHolder.dbHelper.getReadableDatabase(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Consumer.java b/core/src/main/java/de/danoeh/antennapod/core/util/Consumer.java new file mode 100644 index 000000000..13a87af0d --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Consumer.java @@ -0,0 +1,5 @@ +package de.danoeh.antennapod.core.util; + +public interface Consumer<T> { + void accept(T t); +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Function.java b/core/src/main/java/de/danoeh/antennapod/core/util/Function.java new file mode 100644 index 000000000..c4f4ad68a --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Function.java @@ -0,0 +1,7 @@ +package de.danoeh.antennapod.core.util; + +import io.reactivex.annotations.NonNull; + +public interface Function<T, R> { + R apply(@NonNull T t); +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java index 0120790ed..b34ba196d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java @@ -18,12 +18,13 @@ import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.storage.DBWriter; +import io.reactivex.Single; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import rx.Observable; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; public class NetworkUtils { private NetworkUtils(){} @@ -111,11 +112,10 @@ public class NetworkUtils { return null; } - public static Observable<Long> getFeedMediaSizeObservable(FeedMedia media) { - return Observable.create((Observable.OnSubscribe<Long>) subscriber -> { + public static Single<Long> getFeedMediaSizeObservable(FeedMedia media) { + return Single.create((SingleOnSubscribe<Long>) emitter -> { if (!NetworkUtils.isDownloadAllowed()) { - subscriber.onNext(0L); - subscriber.onCompleted(); + emitter.onSuccess(0L); return; } long size = Integer.MIN_VALUE; @@ -129,8 +129,7 @@ public class NetworkUtils { String url = media.getDownload_url(); if(TextUtils.isEmpty(url)) { - subscriber.onNext(0L); - subscriber.onCompleted(); + emitter.onSuccess(0L); return; } @@ -150,8 +149,7 @@ public class NetworkUtils { } } } catch (IOException e) { - subscriber.onNext(0L); - subscriber.onCompleted(); + emitter.onSuccess(0L); Log.e(TAG, Log.getStackTraceString(e)); return; // better luck next time } @@ -163,11 +161,10 @@ public class NetworkUtils { } else { media.setSize(size); } - subscriber.onNext(size); - subscriber.onCompleted(); + emitter.onSuccess(size); DBWriter.setFeedMedia(media); }) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java index 3a2a4ac80..1629f4aaf 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/download/AutoUpdateManager.java @@ -15,8 +15,12 @@ import android.util.Log; import java.util.Calendar; import java.util.concurrent.TimeUnit; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver; import de.danoeh.antennapod.core.service.FeedUpdateJobService; +import de.danoeh.antennapod.core.storage.DBTasks; +import de.danoeh.antennapod.core.util.Converter; +import de.danoeh.antennapod.core.util.FeedUpdateUtils; public class AutoUpdateManager { private static final int JOB_ID_FEED_UPDATE = 42; @@ -153,4 +157,29 @@ public class AutoUpdateManager { updateIntent); Log.d(TAG, "Changed alarm to new time of day " + alarm.get(Calendar.HOUR_OF_DAY) + ":" + alarm.get(Calendar.MINUTE)); } + + /* + * Checks if the app should refresh all feeds, i.e. if the last auto refresh failed. + * + * The feeds are only refreshed if an update interval or time of day is set and the last + * (successful) refresh was before the last interval or more than a day ago, respectively. + * + */ + public static void checkShouldRefreshFeeds(Context context) { + long interval = 0; + if(UserPreferences.getUpdateInterval() > 0) { + interval = UserPreferences.getUpdateInterval(); + } else if(UserPreferences.getUpdateTimeOfDay().length > 0){ + interval = TimeUnit.DAYS.toMillis(1); + } + if(interval == 0) { // auto refresh is disabled + return; + } + long lastRefresh = DBTasks.getLastRefreshAllFeedsTimeMillis(context); + Log.d(TAG, "last refresh: " + Converter.getDurationStringLocalized(context, + System.currentTimeMillis() - lastRefresh) + " ago"); + if(lastRefresh <= System.currentTimeMillis() - interval) { + FeedUpdateUtils.startAutoUpdate(context, null); + } + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java index 16d05dbb9..2b3f38841 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java @@ -35,6 +35,14 @@ public class AudioPlayer extends MediaPlayer implements IPlayer { } @Override + public void setPlaybackParams(float speed, boolean skipSilence) { + if(canSetSpeed()) { + setPlaybackSpeed(speed); + } + //Default player does not support silence skipping + } + + @Override protected boolean useSonic() { return UserPreferences.useSonic(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java index a372f4241..c2b768ea8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java @@ -37,7 +37,7 @@ public interface IPlayer { void setDisplay(SurfaceHolder sh); - void setPlaybackSpeed(float f); + void setPlaybackParams(float speed, boolean skipSilence); void setDownmix(boolean enable); 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 408789cc9..01d6812fd 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 @@ -38,11 +38,12 @@ import de.danoeh.antennapod.core.service.playback.PlayerStatus; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.playback.Playable.PlayableUtils; -import rx.Observable; -import rx.Single; -import rx.Subscription; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; +import io.reactivex.Maybe; +import io.reactivex.MaybeOnSubscribe; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; /** * Communicates with the playback service. GUI classes should use this class to @@ -70,7 +71,8 @@ public abstract class PlaybackController { private boolean released = false; private boolean initialized = false; - private Subscription serviceBinder; + private Disposable serviceBinder; + private Disposable mediaLoader; /** * True if controller should reinit playback service if 'pause' button is @@ -145,7 +147,7 @@ public abstract class PlaybackController { } if(serviceBinder != null) { - serviceBinder.unsubscribe(); + serviceBinder.dispose(); } try { activity.unbindService(mConnection); @@ -180,10 +182,10 @@ public abstract class PlaybackController { private void bindToService() { Log.d(TAG, "Trying to connect to service"); if (serviceBinder != null) { - serviceBinder.unsubscribe(); + serviceBinder.dispose(); } serviceBinder = Observable.fromCallable(this::getPlayLastPlayedMediaIntent) - .subscribeOn(Schedulers.newThread()) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(intent -> { boolean bound = false; @@ -704,6 +706,11 @@ public abstract class PlaybackController { playbackService.setSpeed(speed); } } + public void setSkipSilence(boolean skipSilence) { + if (playbackService != null) { + playbackService.skipSilence(skipSilence); + } + } public void setVolume(float leftVolume, float rightVolume) { if (playbackService != null) { @@ -777,15 +784,18 @@ public abstract class PlaybackController { } private void initServiceNotRunning() { - Single.create(subscriber -> subscriber.onSuccess(getMedia())) - .subscribeOn(Schedulers.newThread()) + mediaLoader = Maybe.create((MaybeOnSubscribe<Playable>) emitter -> { + Playable media = getMedia(); + if (media != null) { + emitter.onSuccess(media); + } else { + emitter.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe((Object media) -> { - if (media == null) { - return; - } - - if (((Playable) media).getMediaType() == MediaType.AUDIO) { + .subscribe(media -> { + if (media.getMediaType() == MediaType.AUDIO) { TypedArray res = activity.obtainStyledAttributes(new int[]{ de.danoeh.antennapod.core.R.attr.av_play_big}); getPlayButton().setImageResource( @@ -794,7 +804,7 @@ public abstract class PlaybackController { } else { getPlayButton().setImageResource(R.drawable.ic_av_play_circle_outline_80dp); } - }); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } /** @@ -802,7 +812,7 @@ public abstract class PlaybackController { */ public class MediaPositionObserver implements Runnable { - public static final int WAITING_INTERVALL = 1000; + static final int WAITING_INTERVALL = 1000; @Override public void run() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java index 1d04fb878..f3c1c4f59 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java @@ -22,9 +22,8 @@ public class VideoPlayer extends MediaPlayer implements IPlayer { } @Override - public void setPlaybackSpeed(float f) { - Log.e(TAG, "Setting playback speed unsupported in video player"); - throw new UnsupportedOperationException("Setting playback speed unsupported in video player"); + public void setPlaybackParams(float speed, boolean skipSilence) { + //Ignore this for non ExoPlayer implementations } @Override |