繁体   English   中英

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

[英]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.

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