1010import android .content .pm .PackageManager ;
1111import android .content .pm .ResolveInfo ;
1212import android .graphics .Bitmap ;
13+ import android .graphics .BitmapFactory ;
1314import android .net .Uri ;
1415import android .os .Build ;
1516import android .text .TextUtils ;
2425import org .schabi .newpipe .BuildConfig ;
2526import org .schabi .newpipe .R ;
2627import org .schabi .newpipe .extractor .Image ;
27- import org .schabi .newpipe .util .image .CoilHelper ;
2828import org .schabi .newpipe .util .image .ImageStrategy ;
2929
30- import java .io . File ;
31- import java .io . FileOutputStream ;
30+ import java .nio . file . Files ;
31+ import java .util . Collections ;
3232import java .util .List ;
3333
34+ import coil .Coil ;
35+ import coil .disk .DiskCache ;
36+ import coil .memory .MemoryCache ;
37+
3438public final class ShareUtils {
3539 private static final String TAG = ShareUtils .class .getSimpleName ();
3640
@@ -335,7 +339,13 @@ public static void copyToClipboard(@NonNull final Context context, final String
335339 }
336340
337341 /**
338- * Generate a {@link ClipData} with the image of the content shared.
342+ * Generate a {@link ClipData} with the image of the content shared, if it's in the app cache.
343+ *
344+ * <p>
345+ * In order not to worry about network issues (timeouts, DNS issues, low connection speed, ...)
346+ * when sharing a content, only images in the {@link MemoryCache} or {@link DiskCache}
347+ * used by the Coil library are used as preview images. If the thumbnail image is not in the
348+ * cache, no {@link ClipData} will be generated and {@code null} will be returned.
339349 *
340350 * <p>
341351 * In order to display the image in the content preview of the Android share sheet, an URI of
@@ -351,11 +361,6 @@ public static void copyToClipboard(@NonNull final Context context, final String
351361 * </p>
352362 *
353363 * <p>
354- * This method will call {@link CoilHelper#loadBitmapBlocking(Context, String)} to get the
355- * thumbnail of the content.
356- * </p>
357- *
358- * <p>
359364 * Using the result of this method when sharing has only an effect on the system share sheet (if
360365 * OEMs didn't change Android system standard behavior) on Android API 29 and higher.
361366 * </p>
@@ -369,33 +374,46 @@ private static ClipData generateClipDataForImagePreview(
369374 @ NonNull final Context context ,
370375 @ NonNull final String thumbnailUrl ) {
371376 try {
372- final var bitmap = CoilHelper .INSTANCE .loadBitmapBlocking (context , thumbnailUrl );
373- if (bitmap == null ) {
374- return null ;
375- }
376-
377377 // Save the image in memory to the application's cache because we need a URI to the
378378 // image to generate a ClipData which will show the share sheet, and so an image file
379379 final Context applicationContext = context .getApplicationContext ();
380- final String appFolder = applicationContext .getCacheDir ().getAbsolutePath ();
381- final File thumbnailPreviewFile = new File (appFolder
382- + "/android_share_sheet_image_preview.jpg" );
380+ final var loader = Coil .imageLoader (context );
381+ final var value = loader .getMemoryCache ()
382+ .get (new MemoryCache .Key (thumbnailUrl , Collections .emptyMap ()));
383+
384+ final Bitmap cachedBitmap ;
385+ if (value != null ) {
386+ cachedBitmap = value .getBitmap ();
387+ } else {
388+ try (var snapshot = loader .getDiskCache ().openSnapshot (thumbnailUrl )) {
389+ if (snapshot != null ) {
390+ cachedBitmap = BitmapFactory .decodeFile (snapshot .getData ().toString ());
391+ } else {
392+ cachedBitmap = null ;
393+ }
394+ }
395+ }
396+
397+ if (cachedBitmap == null ) {
398+ return null ;
399+ }
383400
384- // Any existing file will be overwritten with FileOutputStream
385- final FileOutputStream fileOutputStream = new FileOutputStream (thumbnailPreviewFile );
386- bitmap .compress (Bitmap .CompressFormat .JPEG , 90 , fileOutputStream );
387- fileOutputStream .close ();
401+ final var path = applicationContext .getCacheDir ().toPath ()
402+ .resolve ("android_share_sheet_image_preview.jpg" );
403+ // Any existing file will be overwritten
404+ try (var outputStream = Files .newOutputStream (path )) {
405+ cachedBitmap .compress (Bitmap .CompressFormat .JPEG , 90 , outputStream );
406+ }
388407
389408 final ClipData clipData = ClipData .newUri (applicationContext .getContentResolver (), "" ,
390409 FileProvider .getUriForFile (applicationContext ,
391410 BuildConfig .APPLICATION_ID + ".provider" ,
392- thumbnailPreviewFile ));
411+ path . toFile () ));
393412
394413 if (DEBUG ) {
395414 Log .d (TAG , "ClipData successfully generated for Android share sheet: " + clipData );
396415 }
397416 return clipData ;
398-
399417 } catch (final Exception e ) {
400418 Log .w (TAG , "Error when setting preview image for share sheet" , e );
401419 return null ;
0 commit comments