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)
Advertisement
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) { } });