0

I'm fetching an image from a URL as a bitmap using glide, and onResourceReady() I'm trying to share the image via intent, but I'm getting an exception. I'm using Android 30.

Glide.with(this)
    .asBitmap()
    .load("https://i.imgur.com/lkHKgld.jpeg")
    .into(new CustomTarget<Bitmap>() {
        @Override
        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
            Intent i = new Intent(Intent.ACTION_SEND);
            i.setType("image/*");
            i.putExtra(Intent.EXTRA_STREAM, getLocalBitmapUri(resource));
            startActivity(Intent.createChooser(i, "Share Image"));
        }
            
        @Override
        public void onLoadCleared(@Nullable Drawable placeholder) {
                
        }
    });

My method for providing file URI. Source

public Uri getLocalBitmapUri(Bitmap bmp) {
        Uri bmpUri = null;
        try {
            File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "totka_" + System.currentTimeMillis() + ".png");
            FileOutputStream out = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.close();
            bmpUri = Uri.fromFile(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bmpUri;
    }

MY Error

2021-02-23 01:07:25.750 19345-19345/com.future_tech.hiravoice E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.future_tech.hiravoice, PID: 19345
    com.bumptech.glide.load.engine.CallbackException: Unexpected exception thrown by non-Glide code
        at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:161)
        at com.bumptech.glide.load.engine.EngineJob$CallResourceReady.run(EngineJob.java:428)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:264)
        at android.app.ActivityThread.main(ActivityThread.java:7581)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
     Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.future_tech.hiravoice/files/Pictures/totka_1614060445457.png exposed beyond app through ClipData.Item.getUri()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:2083)
        at android.net.Uri.checkFileUriExposed(Uri.java:2388)
        at android.content.ClipData.prepareToLeaveProcess(ClipData.java:977)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10759)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10765)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:10744)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1710)
        at android.app.Activity.startActivityForResult(Activity.java:5195)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:675)
        at android.app.Activity.startActivityForResult(Activity.java:5153)
        at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:662)
        at android.app.Activity.startActivity(Activity.java:5524)
        at android.app.Activity.startActivity(Activity.java:5492)
        at com.future_tech.hiravoice.activities.AsliTotkayActivity$2.onResourceReady(AsliTotkayActivity.java:185)
        at com.future_tech.hiravoice.activities.AsliTotkayActivity$2.onResourceReady(AsliTotkayActivity.java:179)
        at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:639)
        at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:578)
        at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:159)
        at com.bumptech.glide.load.engine.EngineJob$CallResourceReady.run(EngineJob.java:428) 
        at android.os.Handler.handleCallback(Handler.java:883) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:264) 
        at android.app.ActivityThread.main(ActivityThread.java:7581) 
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)

I also tried using the IntentShare Library

Glide.with(this)
    .asBitmap()
    .load("https://i.imgur.com/lkHKgld.jpeg")
    .into(new CustomTarget<Bitmap>() {
        @Override
        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
            IntentShare.with(getApplicationContext())
                .chooserTitle("Share Totka: ")
                .text("Default text you would like to share.")
                .image(getLocalBitmapUri(resource))
                .deliver();
        }
            
        @Override
        public void onLoadCleared(@Nullable Drawable placeholder) {
                
        }
    });

But there I was getting an error that content Uri is needed.

com.bumptech.glide.load.engine.CallbackException: Unexpected exception thrown by non-Glide code
        at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:161)
        at com.bumptech.glide.load.engine.EngineJob$CallResourceReady.run(EngineJob.java:428)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:264)
        at android.app.ActivityThread.main(ActivityThread.java:7581)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
     Caused by: java.lang.IllegalArgumentException: Invalid image uri : only content scheme supported : file:///storage/emulated/0/Android/data/com.future_tech.hiravoice/files/Pictures/totka_1614061273090.png
        at fr.tvbarthel.intentshare.IntentShare.image(IntentShare.java:229)
        at com.future_tech.hiravoice.activities.AsliTotkayActivity$2.onResourceReady(AsliTotkayActivity.java:186)
        at com.future_tech.hiravoice.activities.AsliTotkayActivity$2.onResourceReady(AsliTotkayActivity.java:180)
        at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:639)
        at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:578)
        at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:159)
Attaullah Khan
  • 303
  • 2
  • 8

2 Answers2

3

Well here is how I got it resolved, first add this provider tag in your manifest

<application>
   ...
   <provider
       android:name="androidx.core.content.FileProvider"
       android:authorities="com.future_tech.hiravoice.fileprovider"
       android:grantUriPermissions="true"
       android:exported="false">
           <meta-data
               android:name="android.support.FILE_PROVIDER_PATHS"
               android:resource="@xml/filepaths" />
   </provider>
</application>

then create a new xml file under res/xml/ named filepaths.xml Source

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--Represents the files in the root directory of the external storage area of ​​the app. The Pictures directory under the Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) directory-->
    <!--/storage/emulated/0/Android/data/com.hm.camerademo/files/Pictures-->
    <external-files-path name="hm_external_files" path="Pictures" />
</paths>

my method for providing file provider uri

public Uri getLocalBitmapUri(Bitmap bmp) {
    Uri bmpUri = null;
    try {
        File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "totka_" + System.currentTimeMillis() + ".png");
        FileOutputStream out = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
        out.close();
        bmpUri = FileProvider.getUriForFile(getApplicationContext(), "com.future_tech.hiravoice.fileprovider", file);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bmpUri;
}

finally the glide with Read URI flag set in intent

Glide.with(this)
    .asBitmap()
    .load("https://i.imgur.com/lkHKgld.jpeg")                
    .into(new CustomTarget<Bitmap>() {
        @Override
        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
            Intent i = new Intent(Intent.ACTION_SEND);
            i.setType("image/*");
            i.putExtra(Intent.EXTRA_STREAM, getLocalBitmapUri(resource));
            i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            startActivity(Intent.createChooser(i, "Share Image"));
        }

        @Override
        public void onLoadCleared(@Nullable Drawable placeholder) {

        }
    });
Attaullah Khan
  • 303
  • 2
  • 8
0

I see this file is stored in "private" files of your app (Android/data/<package_name>, any other app can't fetch them strictly without proper permission from your app

try to grant this permission with this line

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("image/*");
i.putExtra(Intent.EXTRA_STREAM, getLocalBitmapUri(resource));
i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // granting perm!
startActivity(Intent.createChooser(i, "Share Image"));

from DOC

public static final int FLAG_GRANT_READ_URI_PERMISSION

If set, the recipient of this Intent will be granted permission to perform read operations on the URI in the Intent's data and any URIs specified in its ClipData. When applying to an Intent's ClipData, all URIs as well as recursive traversals through data or other ClipData in Intent items will be granted; only the grant flags of the top-level Intent are used.

and HERE we have a doc about sharing

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • tried, still getting error: ```android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.future_tech.hiravoice/files/Pictures/totka_1614065301460.png exposed beyond app through ClipData.Item.getUri()``` – Attaullah Khan Feb 23 '21 at 07:29
  • well, seems like you don't have file provider so you have to implement it, read answer [HERE](https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed). and last linked doc about sharing in my post. edit: glad that you have founded full answer, good luck :) – snachmsm Feb 23 '21 at 09:40