diff options
author | ByteHamster <ByteHamster@users.noreply.github.com> | 2022-11-05 12:50:13 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-05 12:50:13 +0100 |
commit | 546c8841db829a6ac57e8508a91d5734fb4d1ddf (patch) | |
tree | 16e9900d434ebe4def1090b989f8f704340ee7fc /core/src/main | |
parent | 9b06bf0dc595579193ce1893dfe7721f4b5adf0a (diff) | |
parent | c1fbb538058369a4ed5bfcc6ff3622aceb6ce820 (diff) | |
download | AntennaPod-546c8841db829a6ac57e8508a91d5734fb4d1ddf.zip |
Merge pull request #6174 from ByteHamster/modularize-glide
Move Glide config to its own module
Diffstat (limited to 'core/src/main')
16 files changed, 2 insertions, 1127 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 deleted file mode 100644 index 3dfbb6f03..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java +++ /dev/null @@ -1,53 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Bitmap; -import android.util.Log; - -import androidx.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.AppGlideModule; - -import de.danoeh.antennapod.model.feed.EmbeddedChapterImage; -import java.io.InputStream; - -import com.bumptech.glide.request.RequestOptions; -import java.nio.ByteBuffer; - -/** - * {@see com.bumptech.glide.integration.okhttp.OkHttpGlideModule} - */ -@GlideModule -public class ApGlideModule extends AppGlideModule { - private static final String TAG = "ApGlideModule"; - private static final long MEGABYTES = 1024 * 1024; - private static final long GIGABYTES = 1024 * 1024 * 1024; - - @Override - public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) { - builder.setDefaultRequestOptions(RequestOptions.formatOf(DecodeFormat.PREFER_ARGB_8888)); - builder.setLogLevel(Log.WARN); - @SuppressLint("UsableSpace") - long spaceAvailable = context.getCacheDir().getUsableSpace(); - long imageCacheSize = (spaceAvailable > 2 * GIGABYTES) ? (250 * MEGABYTES) : (50 * MEGABYTES); - Log.d(TAG, "Free space on cache dir: " + spaceAvailable + ", using image cache size: " + imageCacheSize); - builder.setDiskCache(new InternalCacheDiskCacheFactory(context, imageCacheSize)); - } - - @Override - public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { - registry.replace(String.class, InputStream.class, new MetadataRetrieverLoader.Factory(context)); - registry.append(String.class, InputStream.class, new GenerativePlaceholderImageModelLoader.Factory()); - registry.append(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); - registry.append(String.class, InputStream.class, new NoHttpStringLoader.StreamFactory()); - - registry.append(EmbeddedChapterImage.class, ByteBuffer.class, new ChapterImageModelLoader.Factory()); - registry.register(Bitmap.class, PaletteBitmap.class, new PaletteBitmapTranscoder()); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java deleted file mode 100644 index d0061af99..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import com.bumptech.glide.load.engine.DiskCacheStrategy; - -/** - * The settings that AntennaPod will use for various Glide options - */ -public class ApGlideSettings { - private ApGlideSettings(){} - - public static final DiskCacheStrategy AP_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL; -} 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 deleted file mode 100644 index bab50a7b4..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ /dev/null @@ -1,113 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.content.ContentResolver; -import android.text.TextUtils; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -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; -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.util.NetworkUtils; -import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedMedia; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Protocol; -import okhttp3.Response; -import okhttp3.ResponseBody; - -import java.io.IOException; -import java.io.InputStream; - -/** - * {@see com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader}. - */ -class ApOkHttpUrlLoader implements ModelLoader<String, InputStream> { - - /** - * The default factory for {@link ApOkHttpUrlLoader}s. - */ - public static class Factory implements ModelLoaderFactory<String, InputStream> { - - private static volatile OkHttpClient internalClient; - private final OkHttpClient client; - - private static OkHttpClient getInternalClient() { - if (internalClient == null) { - synchronized (Factory.class) { - if (internalClient == null) { - OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder(); - builder.interceptors().add(new NetworkAllowanceInterceptor()); - builder.cache(null); // Handled by Glide - internalClient = builder.build(); - } - } - } - return internalClient; - } - - /** - * Constructor for a new Factory that runs requests using a static singleton client. - */ - Factory() { - this.client = getInternalClient(); - } - - @NonNull - @Override - public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) { - return new ApOkHttpUrlLoader(client); - } - - @Override - public void teardown() { - // Do nothing, this instance doesn't own the client. - } - } - - private final OkHttpClient client; - - private ApOkHttpUrlLoader(OkHttpClient client) { - this.client = client; - } - - @Nullable - @Override - public LoadData<InputStream> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) { - return new LoadData<>(new ObjectKey(model), new ResizingOkHttpStreamFetcher(client, new GlideUrl(model))); - } - - @Override - public boolean handles(@NonNull String model) { - return !TextUtils.isEmpty(model) - // If the other loaders fail, do not attempt to load as web resource - && !model.startsWith(Feed.PREFIX_GENERATIVE_COVER) - && !model.startsWith(FeedMedia.FILENAME_PREFIX_EMBEDDED_COVER) - // Leave content URIs to Glide's default loaders - && !model.startsWith(ContentResolver.SCHEME_CONTENT) - && !model.startsWith(ContentResolver.SCHEME_ANDROID_RESOURCE); - } - - private static class NetworkAllowanceInterceptor implements Interceptor { - - @NonNull - @Override - public Response intercept(@NonNull Chain chain) throws IOException { - if (NetworkUtils.isImageAllowed()) { - return chain.proceed(chain.request()); - } else { - return new Response.Builder() - .protocol(Protocol.HTTP_2) - .code(420) - .message("Policy Not Fulfilled") - .body(ResponseBody.create(null, new byte[0])) - .request(chain.request()) - .build(); - } - } - } -}
\ No newline at end of file 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 deleted file mode 100644 index 2fffad108..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/AudioCoverFetcher.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.content.ContentResolver; -import android.content.Context; -import android.media.MediaMetadataRetriever; - -import android.net.Uri; -import androidx.annotation.NonNull; -import com.bumptech.glide.Priority; -import com.bumptech.glide.load.DataSource; -import com.bumptech.glide.load.data.DataFetcher; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -// see https://github.com/bumptech/glide/issues/699 -class AudioCoverFetcher implements DataFetcher<InputStream> { - private final String path; - private final Context context; - - public AudioCoverFetcher(String path, Context context) { - this.path = path; - this.context = context; - } - - @Override - public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) { - try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) { - if (path.startsWith(ContentResolver.SCHEME_CONTENT)) { - retriever.setDataSource(context, Uri.parse(path)); - } else { - retriever.setDataSource(path); - } - byte[] picture = retriever.getEmbeddedPicture(); - if (picture != null) { - callback.onDataReady(new ByteArrayInputStream(picture)); - } - } catch (Exception e) { - callback.onLoadFailed(e); - } - } - - @Override public void cleanup() { - // nothing to clean up - } - - @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/ChapterImageModelLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java deleted file mode 100644 index 63126405d..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java +++ /dev/null @@ -1,111 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import androidx.annotation.NonNull; -import com.bumptech.glide.Priority; -import com.bumptech.glide.load.DataSource; -import com.bumptech.glide.load.Options; -import com.bumptech.glide.load.data.DataFetcher; -import com.bumptech.glide.load.model.ModelLoader; -import com.bumptech.glide.load.model.ModelLoaderFactory; -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.model.feed.EmbeddedChapterImage; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import okhttp3.Request; -import okhttp3.Response; -import org.apache.commons.io.IOUtils; - -public final class ChapterImageModelLoader implements ModelLoader<EmbeddedChapterImage, ByteBuffer> { - - public static class Factory implements ModelLoaderFactory<EmbeddedChapterImage, ByteBuffer> { - @NonNull - @Override - public ModelLoader<EmbeddedChapterImage, ByteBuffer> build(@NonNull MultiModelLoaderFactory unused) { - return new ChapterImageModelLoader(); - } - - @Override - public void teardown() { - // Do nothing. - } - } - - @Override - public LoadData<ByteBuffer> buildLoadData(@NonNull EmbeddedChapterImage model, - int width, - int height, - @NonNull Options options) { - return new LoadData<>(new ObjectKey(model), new EmbeddedImageFetcher(model)); - } - - @Override - public boolean handles(@NonNull EmbeddedChapterImage model) { - return true; - } - - static class EmbeddedImageFetcher implements DataFetcher<ByteBuffer> { - private final EmbeddedChapterImage image; - - public EmbeddedImageFetcher(EmbeddedChapterImage image) { - this.image = image; - } - - @Override - public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super ByteBuffer> callback) { - - BufferedInputStream stream = null; - try { - if (image.getMedia().localFileAvailable()) { - File localFile = new File(image.getMedia().getLocalMediaUrl()); - stream = new BufferedInputStream(new FileInputStream(localFile)); - IOUtils.skip(stream, image.getPosition()); - byte[] imageContent = new byte[image.getLength()]; - IOUtils.read(stream, imageContent, 0, image.getLength()); - callback.onDataReady(ByteBuffer.wrap(imageContent)); - } else { - Request.Builder httpReq = new Request.Builder(); - // Skipping would download the whole file - httpReq.header("Range", "bytes=" + image.getPosition() - + "-" + (image.getPosition() + image.getLength())); - httpReq.url(image.getMedia().getStreamUrl()); - Response response = AntennapodHttpClient.getHttpClient().newCall(httpReq.build()).execute(); - if (!response.isSuccessful() || response.body() == null) { - throw new IOException("Invalid response: " + response.code() + " " + response.message()); - } - callback.onDataReady(ByteBuffer.wrap(response.body().bytes())); - } - } catch (IOException e) { - callback.onLoadFailed(e); - } finally { - IOUtils.closeQuietly(stream); - } - } - - @Override - public void cleanup() { - // nothing to clean up - } - - @Override - public void cancel() { - // cannot cancel - } - - @NonNull - @Override - public Class<ByteBuffer> getDataClass() { - return ByteBuffer.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 deleted file mode 100644 index 29edfb478..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java +++ /dev/null @@ -1,294 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.graphics.Bitmap; -import android.media.ThumbnailUtils; -import androidx.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.nio.charset.Charset; -import java.security.MessageDigest; - -public class FastBlurTransformation extends BitmapTransformation { - private static final String ID = "de.danoeh.antennapod.core.glide.FastBlurTransformation"; - - private static final String TAG = FastBlurTransformation.class.getSimpleName(); - - private static final int STACK_BLUR_RADIUS = 10; - - public FastBlurTransformation() { - super(); - } - - @Override - protected Bitmap transform(@NonNull BitmapPool pool, - @NonNull Bitmap source, - int outWidth, - int outHeight) { - int targetWidth = outWidth / 3; - int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth); - Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight); - Bitmap result = fastBlur(resized, STACK_BLUR_RADIUS); - if (result == null) { - Log.w(TAG, "result was null"); - return source; - } - return result; - } - - @Override - public boolean equals(Object o) { - return o instanceof FastBlurTransformation; - } - - @Override - public int hashCode() { - return ID.hashCode(); - } - - @Override - public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { - messageDigest.update(TAG.getBytes(Charset.defaultCharset())); - } - - private static Bitmap fastBlur(Bitmap bitmap, int radius) { - - // Stack Blur v1.0 from - // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html - // - // Java Author: Mario Klingemann <mario at quasimondo.com> - // http://incubator.quasimondo.com - // created Feburary 29, 2004 - // Android port : Yahel Bouaziz <yahel at kayenko.com> - // http://www.kayenko.com - // ported april 5th, 2012 - - // This is a compromise between Gaussian Blur and Box blur - // It creates much better looking blurs than Box Blur, but is - // 7x faster than my Gaussian Blur implementation. - // - // I called it Stack Blur because this describes best how this - // filter works internally: it creates a kind of moving stack - // of colors whilst scanning through the image. Thereby it - // just has to add one new block of color to the right side - // of the stack and remove the leftmost color. The remaining - // colors on the topmost layer of the stack are either added on - // or reduced by one, depending on if they are on the right or - // on the left side of the stack. - // - // If you are using this algorithm in your code please add - // the following line: - // - // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com> - - if (radius < 1) { - return null; - } - - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - int[] pix = new int[w * h]; - bitmap.getPixels(pix, 0, w, 0, 0, w, h); - - int wm = w - 1; - int hm = h - 1; - int wh = w * h; - int div = radius + radius + 1; - - int[] r = new int[wh]; - int[] g = new int[wh]; - int[] b = new int[wh]; - int rsum; - int gsum; - int bsum; - int x; - int y; - int i; - int p; - int yp; - int yi; - int yw; - int[] vmin = new int[Math.max(w, h)]; - - int divsum = (div + 1) >> 1; - divsum *= divsum; - int[] dv = new int[256 * divsum]; - for (i = 0; i < 256 * divsum; i++) { - dv[i] = (i / divsum); - } - - yw = yi = 0; - - int[][] stack = new int[div][3]; - int stackpointer; - int stackstart; - int[] sir; - int rbs; - int r1 = radius + 1; - int routsum; - int goutsum; - int boutsum; - int rinsum; - int ginsum; - int binsum; - - for (y = 0; y < h; y++) { - rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; - for (i = -radius; i <= radius; i++) { - p = pix[yi + Math.min(wm, Math.max(i, 0))]; - sir = stack[i + radius]; - sir[0] = (p & 0xff0000) >> 16; - sir[1] = (p & 0x00ff00) >> 8; - sir[2] = (p & 0x0000ff); - rbs = r1 - Math.abs(i); - rsum += sir[0] * rbs; - gsum += sir[1] * rbs; - bsum += sir[2] * rbs; - if (i > 0) { - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - } else { - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - } - } - stackpointer = radius; - - for (x = 0; x < w; x++) { - - r[yi] = dv[rsum]; - g[yi] = dv[gsum]; - b[yi] = dv[bsum]; - - rsum -= routsum; - gsum -= goutsum; - bsum -= boutsum; - - stackstart = stackpointer - radius + div; - sir = stack[stackstart % div]; - - routsum -= sir[0]; - goutsum -= sir[1]; - boutsum -= sir[2]; - - if (y == 0) { - vmin[x] = Math.min(x + radius + 1, wm); - } - p = pix[yw + vmin[x]]; - - sir[0] = (p & 0xff0000) >> 16; - sir[1] = (p & 0x00ff00) >> 8; - sir[2] = (p & 0x0000ff); - - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - - rsum += rinsum; - gsum += ginsum; - bsum += binsum; - - stackpointer = (stackpointer + 1) % div; - sir = stack[(stackpointer) % div]; - - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - - rinsum -= sir[0]; - ginsum -= sir[1]; - binsum -= sir[2]; - - yi++; - } - yw += w; - } - for (x = 0; x < w; x++) { - rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; - yp = -radius * w; - for (i = -radius; i <= radius; i++) { - yi = Math.max(0, yp) + x; - - sir = stack[i + radius]; - - sir[0] = r[yi]; - sir[1] = g[yi]; - sir[2] = b[yi]; - - rbs = r1 - Math.abs(i); - - rsum += r[yi] * rbs; - gsum += g[yi] * rbs; - bsum += b[yi] * rbs; - - if (i > 0) { - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - } else { - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - } - - if (i < hm) { - yp += w; - } - } - yi = x; - stackpointer = radius; - for (y = 0; y < h; y++) { - // Set alpha to 1 - pix[yi] = 0xff000000 | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; - - rsum -= routsum; - gsum -= goutsum; - bsum -= boutsum; - - stackstart = stackpointer - radius + div; - sir = stack[stackstart % div]; - - routsum -= sir[0]; - goutsum -= sir[1]; - boutsum -= sir[2]; - - if (x == 0) { - vmin[y] = Math.min(y + r1, hm) * w; - } - p = x + vmin[y]; - - sir[0] = r[p]; - sir[1] = g[p]; - sir[2] = b[p]; - - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - - rsum += rinsum; - gsum += ginsum; - bsum += binsum; - - stackpointer = (stackpointer + 1) % div; - sir = stack[stackpointer]; - - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - - rinsum -= sir[0]; - ginsum -= sir[1]; - binsum -= sir[2]; - - yi += w; - } - } - bitmap.setPixels(pix, 0, w, 0, 0, w, h); - return bitmap; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/GenerativePlaceholderImageModelLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/GenerativePlaceholderImageModelLoader.java deleted file mode 100644 index a2263bc28..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/GenerativePlaceholderImageModelLoader.java +++ /dev/null @@ -1,139 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.LinearGradient; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.Shader; -import androidx.annotation.NonNull; -import com.bumptech.glide.Priority; -import com.bumptech.glide.load.DataSource; -import com.bumptech.glide.load.Options; -import com.bumptech.glide.load.data.DataFetcher; -import com.bumptech.glide.load.model.ModelLoader; -import com.bumptech.glide.load.model.ModelLoaderFactory; -import com.bumptech.glide.load.model.MultiModelLoaderFactory; -import com.bumptech.glide.signature.ObjectKey; -import de.danoeh.antennapod.model.feed.Feed; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.util.Random; - -public final class GenerativePlaceholderImageModelLoader implements ModelLoader<String, InputStream> { - - public static class Factory implements ModelLoaderFactory<String, InputStream> { - @NonNull - @Override - public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory unused) { - return new GenerativePlaceholderImageModelLoader(); - } - - @Override - public void teardown() { - // Do nothing. - } - } - - @Override - public LoadData<InputStream> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) { - return new LoadData<>(new ObjectKey(model), new EmbeddedImageFetcher(model, width, height)); - } - - @Override - public boolean handles(@NonNull String model) { - return model.startsWith(Feed.PREFIX_GENERATIVE_COVER); - } - - static class EmbeddedImageFetcher implements DataFetcher<InputStream> { - private static final int[] PALETTES = {0xff78909c, 0xffff6f00, 0xff388e3c, - 0xff00838f, 0xff7b1fa2, 0xffb71c1c, 0xff2196f3}; - private final String model; - private final int width; - private final int height; - - public EmbeddedImageFetcher(String model, int width, int height) { - this.model = model; - this.width = width; - this.height = height; - } - - @Override - public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) { - final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(bitmap); - final Random generator = new Random(model.hashCode()); - final int lineGridSteps = 4 + generator.nextInt(4); - final int slope = width / 4; - final float shadowWidth = width * 0.01f; - final float lineDistance = ((float) width / (lineGridSteps - 2)); - final int baseColor = PALETTES[generator.nextInt(PALETTES.length)]; - - Paint paint = new Paint(); - int color = randomShadeOfGrey(generator); - paint.setColor(color); - paint.setStrokeWidth(lineDistance); - paint.setColorFilter(new PorterDuffColorFilter(baseColor, PorterDuff.Mode.MULTIPLY)); - Paint paintShadow = new Paint(); - paintShadow.setColor(0xff000000); - paintShadow.setStrokeWidth(lineDistance); - - int forcedColorChange = 1 + generator.nextInt(lineGridSteps - 2); - for (int i = lineGridSteps - 1; i >= 0; i--) { - float linePos = (i - 0.5f) * lineDistance; - boolean switchColor = generator.nextFloat() < 0.3f || i == forcedColorChange; - if (switchColor) { - int newColor = color; - while (newColor == color) { - newColor = randomShadeOfGrey(generator); - } - color = newColor; - paint.setColor(newColor); - canvas.drawLine(linePos + slope + shadowWidth, -slope, - linePos - slope + shadowWidth, height + slope, paintShadow); - } - canvas.drawLine(linePos + slope, -slope, - linePos - slope, height + slope, paint); - } - - Paint gradientPaint = new Paint(); - paint.setDither(true); - gradientPaint.setShader(new LinearGradient(0, 0, 0, height, 0x00000000, 0x55000000, Shader.TileMode.CLAMP)); - canvas.drawRect(0, 0, width, height, gradientPaint); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); - InputStream is = new ByteArrayInputStream(baos.toByteArray()); - callback.onDataReady(is); - } - - private static int randomShadeOfGrey(Random generator) { - return 0xff777777 + 0x222222 * generator.nextInt(5); - } - - @Override - public void cleanup() { - // nothing to clean up - } - - @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/MetadataRetrieverLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/MetadataRetrieverLoader.java deleted file mode 100644 index 1be43052b..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/MetadataRetrieverLoader.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.bumptech.glide.load.Options; -import com.bumptech.glide.load.model.ModelLoader; -import com.bumptech.glide.load.model.ModelLoaderFactory; -import com.bumptech.glide.load.model.MultiModelLoaderFactory; -import com.bumptech.glide.signature.ObjectKey; -import de.danoeh.antennapod.model.feed.FeedMedia; - -import java.io.InputStream; - -class MetadataRetrieverLoader implements ModelLoader<String, InputStream> { - - /** - * The default factory for {@link MetadataRetrieverLoader}s. - */ - public static class Factory implements ModelLoaderFactory<String, InputStream> { - private final Context context; - - Factory(Context context) { - this.context = context; - } - - @NonNull - @Override - public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) { - return new MetadataRetrieverLoader(context); - } - - @Override - public void teardown() { - // Do nothing, this instance doesn't own the client. - } - } - - private final Context context; - - private MetadataRetrieverLoader(Context context) { - this.context = context; - } - - @Nullable - @Override - public LoadData<InputStream> buildLoadData(@NonNull String model, - int width, int height, @NonNull Options options) { - return new LoadData<>(new ObjectKey(model), - new AudioCoverFetcher(model.replace(FeedMedia.FILENAME_PREFIX_EMBEDDED_COVER, ""), context)); - } - - @Override - public boolean handles(@NonNull String model) { - return model.startsWith(FeedMedia.FILENAME_PREFIX_EMBEDDED_COVER); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/NoHttpStringLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/NoHttpStringLoader.java deleted file mode 100644 index fab470984..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/NoHttpStringLoader.java +++ /dev/null @@ -1,45 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.net.Uri; -import androidx.annotation.NonNull; -import com.bumptech.glide.load.model.ModelLoader; -import com.bumptech.glide.load.model.ModelLoaderFactory; -import com.bumptech.glide.load.model.MultiModelLoaderFactory; -import com.bumptech.glide.load.model.StringLoader; -import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedMedia; - -import java.io.InputStream; - -/** - * StringLoader that does not handle http/https urls. Used to avoid fallback to StringLoader when - * AntennaPod blocks mobile image loading. - */ -public final class NoHttpStringLoader extends StringLoader<InputStream> { - - public static class StreamFactory implements ModelLoaderFactory<String, InputStream> { - @NonNull - @Override - public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) { - return new NoHttpStringLoader(multiFactory.build(Uri.class, InputStream.class)); - } - - @Override - public void teardown() { - // Do nothing. - } - } - - public NoHttpStringLoader(ModelLoader<Uri, InputStream> uriLoader) { - super(uriLoader); - } - - @Override - public boolean handles(@NonNull String model) { - return !model.startsWith("http") - // If the custom loaders fail, do not attempt to load with Glide internal loaders - && !model.startsWith(Feed.PREFIX_GENERATIVE_COVER) - && !model.startsWith(FeedMedia.FILENAME_PREFIX_EMBEDDED_COVER) - && super.handles(model); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmap.java b/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmap.java deleted file mode 100644 index 59ecd3d0d..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmap.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Source: https://github.com/bumptech/glide/wiki/Custom-targets#palette-example - */ - -package de.danoeh.antennapod.core.glide; - -import android.graphics.Bitmap; - -import androidx.annotation.NonNull; -import androidx.palette.graphics.Palette; - -public class PaletteBitmap { - public final Palette palette; - public final Bitmap bitmap; - - public PaletteBitmap(@NonNull Bitmap bitmap, Palette palette) { - this.bitmap = bitmap; - this.palette = palette; - } -}
\ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmapResource.java b/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmapResource.java deleted file mode 100644 index fef0bccd3..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmapResource.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Source: https://github.com/bumptech/glide/wiki/Custom-targets#palette-example - */ - -package de.danoeh.antennapod.core.glide; - -import androidx.annotation.NonNull; - -import com.bumptech.glide.load.engine.Resource; -import com.bumptech.glide.util.Util; - -public class PaletteBitmapResource implements Resource<PaletteBitmap> { - private final PaletteBitmap paletteBitmap; - - public PaletteBitmapResource(@NonNull PaletteBitmap paletteBitmap) { - this.paletteBitmap = paletteBitmap; - } - - @NonNull - @Override - public Class<PaletteBitmap> getResourceClass() { - return PaletteBitmap.class; - } - - @NonNull - @Override - public PaletteBitmap get() { - return paletteBitmap; - } - - @Override - public int getSize() { - return Util.getBitmapByteSize(paletteBitmap.bitmap); - } - - @Override - public void recycle() { - paletteBitmap.bitmap.recycle(); - } -}
\ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmapTranscoder.java b/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmapTranscoder.java deleted file mode 100644 index a6a606cb8..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/PaletteBitmapTranscoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Source: https://github.com/bumptech/glide/wiki/Custom-targets#palette-example - */ - -package de.danoeh.antennapod.core.glide; - -import android.graphics.Bitmap; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.palette.graphics.Palette; - -import com.bumptech.glide.load.Options; -import com.bumptech.glide.load.engine.Resource; -import com.bumptech.glide.load.resource.transcode.ResourceTranscoder; - -import de.danoeh.antennapod.core.preferences.UserPreferences; - -public class PaletteBitmapTranscoder implements ResourceTranscoder<Bitmap, PaletteBitmap> { - - @Nullable - @Override - public Resource<PaletteBitmap> transcode(@NonNull Resource<Bitmap> toTranscode, @NonNull Options options) { - Bitmap bitmap = toTranscode.get(); - Palette palette = null; - if (UserPreferences.shouldShowSubscriptionTitle()) { - palette = new Palette.Builder(bitmap).generate(); - } - PaletteBitmap result = new PaletteBitmap(bitmap, palette); - return new PaletteBitmapResource(result); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java deleted file mode 100644 index 1871723bb..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java +++ /dev/null @@ -1,137 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Build; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.bumptech.glide.Priority; -import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher; -import com.bumptech.glide.load.model.GlideUrl; -import okhttp3.Call; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class ResizingOkHttpStreamFetcher extends OkHttpStreamFetcher { - private static final String TAG = "ResizingOkHttpStreamFet"; - private static final int MAX_DIMENSIONS = 1500; - private static final int MAX_FILE_SIZE = 1024 * 1024; // 1 MB - - private FileInputStream stream; - private File tempIn; - private File tempOut; - - public ResizingOkHttpStreamFetcher(Call.Factory client, GlideUrl url) { - super(client, url); - } - - @Override - public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) { - super.loadData(priority, new DataCallback<InputStream>() { - @Override - public void onDataReady(@Nullable InputStream data) { - if (data == null) { - callback.onDataReady(null); - return; - } - try { - tempIn = File.createTempFile("resize_", null); - tempOut = File.createTempFile("resize_", null); - OutputStream outputStream = new FileOutputStream(tempIn); - IOUtils.copy(data, outputStream); - outputStream.close(); - IOUtils.closeQuietly(data); - - if (tempIn.length() <= MAX_FILE_SIZE) { - try { - stream = new FileInputStream(tempIn); - callback.onDataReady(stream); // Just deliver the original, non-scaled image - } catch (FileNotFoundException fileNotFoundException) { - callback.onLoadFailed(fileNotFoundException); - } - return; - } - - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - FileInputStream in = new FileInputStream(tempIn); - BitmapFactory.decodeStream(in, null, options); - IOUtils.closeQuietly(in); - - if (options.outWidth == -1 || options.outHeight == -1) { - throw new IOException("Not a valid image"); - } else if (Math.max(options.outHeight, options.outWidth) >= MAX_DIMENSIONS) { - double sampleSize = (double) Math.max(options.outHeight, options.outWidth) / MAX_DIMENSIONS; - options.inSampleSize = (int) Math.pow(2d, Math.floor(Math.log(sampleSize) / Math.log(2d))); - } - - options.inJustDecodeBounds = false; - in = new FileInputStream(tempIn); - Bitmap bitmap = BitmapFactory.decodeStream(in, null, options); - IOUtils.closeQuietly(in); - - Bitmap.CompressFormat format = Build.VERSION.SDK_INT < 30 - ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.WEBP_LOSSY; - - int quality = 100; - while (true) { - FileOutputStream out = new FileOutputStream(tempOut); - bitmap.compress(format, quality, out); - IOUtils.closeQuietly(out); - - if (tempOut.length() > 3 * MAX_FILE_SIZE && quality >= 45) { - quality -= 40; - } else if (tempOut.length() > 2 * MAX_FILE_SIZE && quality >= 25) { - quality -= 20; - } else if (tempOut.length() > MAX_FILE_SIZE && quality >= 15) { - quality -= 10; - } else if (tempOut.length() > MAX_FILE_SIZE && quality >= 10) { - quality -= 5; - } else { - break; - } - } - bitmap.recycle(); - - stream = new FileInputStream(tempOut); - callback.onDataReady(stream); - Log.d(TAG, "Compressed image from " + tempIn.length() / 1024 - + " to " + tempOut.length() / 1024 + " kB (quality: " + quality + "%)"); - } catch (Throwable e) { - e.printStackTrace(); - - try { - stream = new FileInputStream(tempIn); - callback.onDataReady(stream); // Just deliver the original, non-scaled image - } catch (FileNotFoundException fileNotFoundException) { - e.printStackTrace(); - callback.onLoadFailed(fileNotFoundException); - } - } - } - - @Override - public void onLoadFailed(@NonNull Exception e) { - callback.onLoadFailed(e); - } - }); - } - - @Override - public void cleanup() { - IOUtils.closeQuietly(stream); - FileUtils.deleteQuietly(tempIn); - FileUtils.deleteQuietly(tempOut); - super.cleanup(); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java index b6a1851fa..c0cf9e077 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java @@ -19,7 +19,6 @@ import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedCounter; import de.danoeh.antennapod.model.feed.FeedPreferences; -import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.util.gui.NotificationUtils; import de.danoeh.antennapod.storage.database.PodDBAdapter; @@ -119,9 +118,7 @@ public class NewEpisodesNotification { return Glide.with(context) .asBitmap() .load(feed.getImageUrl()) - .apply(new RequestOptions() - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .centerCrop()) + .apply(new RequestOptions().centerCrop()) .submit(iconSize, iconSize) .get(); } catch (Throwable tr) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java index 47b587d77..3d5b4224c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java @@ -20,7 +20,6 @@ import androidx.core.content.ContextCompat; import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.util.Converter; @@ -72,9 +71,7 @@ public class PlaybackServiceNotificationBuilder { public void loadIcon() { int iconSize = (int) (128 * context.getResources().getDisplayMetrics().density); - final RequestOptions options = new RequestOptions() - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .centerCrop(); + final RequestOptions options = new RequestOptions().centerCrop(); try { icon = Glide.with(context) .asBitmap() diff --git a/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java index 1d1017bdc..b71e4ae80 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java +++ b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java @@ -13,14 +13,12 @@ import android.view.View; import android.widget.RemoteViews; import com.bumptech.glide.Glide; -import com.bumptech.glide.request.RequestOptions; import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.model.playback.MediaType; -import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.receiver.PlayerWidget; import de.danoeh.antennapod.core.util.Converter; @@ -89,7 +87,6 @@ public abstract class WidgetUpdater { icon = Glide.with(context) .asBitmap() .load(widgetState.media.getImageLocation()) - .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY)) .submit(iconSize, iconSize) .get(500, TimeUnit.MILLISECONDS); views.setImageViewBitmap(R.id.imgvCover, icon); @@ -98,7 +95,6 @@ public abstract class WidgetUpdater { icon = Glide.with(context) .asBitmap() .load(ImageResourceUtils.getFallbackImageLocation(widgetState.media)) - .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY)) .submit(iconSize, iconSize) .get(500, TimeUnit.MILLISECONDS); views.setImageViewBitmap(R.id.imgvCover, icon); |