简体   繁体   English

如何在 android 10 中通过意图共享图像

[英]How to share image via intent in android 10

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.我正在使用滑翔从 URL 作为 bitmap 获取图像,并且onResourceReady()我试图通过意图共享图像,但出现异常。 I'm using Android 30.我正在使用 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.我提供文件 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我也尝试使用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) {
                
        }
    });

But there I was getting an error that content Uri is needed.但是我收到了一个错误,即需要内容 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)

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然后在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>

my method for providing file provider uri我提供文件提供程序 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最后,在 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) {

        }
    });

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我看到此文件存储在您的应用程序的“私有”文件中( Android/data/<package_name> ,未经您的应用程序的适当许可,任何其他应用程序都无法严格获取它们

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来自DOC

public static final int FLAG_GRANT_READ_URI_PERMISSION公共 static 最终 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.如果设置,此 Intent 的接收者将被授予对 Intent 数据中的 URI 及其 ClipData 中指定的任何 URI 执行读取操作的权限。 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;当应用于 Intent 的 ClipData 时,所有 URI 以及通过数据或 Intent 项中的其他 ClipData 的递归遍历都将被授予; only the grant flags of the top-level Intent are used.仅使用顶级 Intent 的授权标志。

and HERE we have a doc about sharing这里我们有一个关于分享的文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM