[英]How to share image via intent in android 10
我正在使用滑翔从 URL 作为 bitmap 获取图像,并且onResourceReady()
我试图通过意图共享图像,但出现异常。 我正在使用 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) {
}
});
我提供文件 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 = Uri.fromFile(file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
}
我的错误
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)
我也尝试使用IntentShare 库
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) {
}
});
但是我收到了一个错误,即需要内容 Uri。
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)
那么这就是我解决它的方法,首先在你的清单中添加这个提供者标签
<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>
然后在res/xml/
下新建一个 xml 文件,命名为filepaths.xml
源
<?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>
我提供文件提供程序 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;
}
最后,在 Intent 中设置了 Read URI 标志的滑行
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) {
}
});
我看到此文件存储在您的应用程序的“私有”文件中( Android/data/<package_name>
,未经您的应用程序的适当许可,任何其他应用程序都无法严格获取它们
尝试使用此行授予此权限
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"));
来自DOC
公共 static 最终 int FLAG_GRANT_READ_URI_PERMISSION
如果设置,此 Intent 的接收者将被授予对 Intent 数据中的 URI 及其 ClipData 中指定的任何 URI 执行读取操作的权限。 当应用于 Intent 的 ClipData 时,所有 URI 以及通过数据或 Intent 项中的其他 ClipData 的递归遍历都将被授予; 仅使用顶级 Intent 的授权标志。
在这里我们有一个关于分享的文档
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.