How to share image via intent in android 10

Tags: , ,



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)

Answer

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) {

        }
    });


Source: stackoverflow