java.lang.RuntimeException:通过意图传递位图时系统失败

java.lang.RuntimeException: Failure from system while passing bitmap through intent

我正在尝试通过 Intent 将图像分享给其他应用程序。这是我的逻辑:

public void doSocialShare(String title, String text, Bitmap resource) {

        Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
        sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        sendIntent.putExtra(Intent.EXTRA_TEXT, text);
        sendIntent.putExtra(Intent.EXTRA_STREAM, resource);
        sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        sendIntent.setType("image/*");

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
            Log.d("INFORMATION", "The current android version allow us to know what app is chosen by the user.");

            Intent receiverIntent = new Intent(this, ShareBroadcastReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
            sendIntent = Intent.createChooser(sendIntent, "Share via...", pendingIntent.getIntentSender());
        }
        startActivity(sendIntent);
    }

这就是我调用 doSocialShare() 方法的方式:

BitmapDrawable drawable = (BitmapDrawable) img_FPO.getDrawable();
                Bitmap bitmap = drawable.getBitmap();
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 30, out);
                Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));

                doSocialShare("Share To", "#Smile", decoded);

但是我收到了这个错误。这是因为位图大小。我该如何解决这个问题?:

E/AndroidRuntime: FATAL EXCEPTION: main
                                                                            Process: com.aligntech.myinvisalign, PID: 31495
                                                                            java.lang.RuntimeException: Failure from system
                                                                                at android.app.Instrumentation.execStartActivity(Instrumentation.java:1533)
                                                                                at android.app.Activity.startActivityForResult(Activity.java:4403)
                                                                                at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54)
                                                                                at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:67)
                                                                                at android.app.Activity.startActivityForResult(Activity.java:4362)
                                                                                at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:732)
                                                                                at android.app.Activity.startActivity(Activity.java:4686)
                                                                                at android.app.Activity.startActivity(Activity.java:4654)
                                                                                at com.aligntech.myinvisalign.Activities.PhotoDetailActivity.doSocialShare(PhotoDetailActivity.java:800)
                                                                                at com.aligntech.myinvisalign.Activities.PhotoDetailActivity.onShareItemClick(PhotoDetailActivity.java:745)
                                                                                at com.aligntech.myinvisalign.Adapters.HorizontalRecyclerAdapter.onClick(HorizontalRecyclerAdapter.java:138)
                                                                                at android.view.View.performClick(View.java:6265)
                                                                                at android.view.View$PerformClick.run(View.java:23764)
                                                                                at android.os.Handler.handleCallback(Handler.java:751)
                                                                                at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                at android.os.Looper.loop(Looper.java:154)
                                                                                at android.app.ActivityThread.main(ActivityThread.java:6776)
                                                                                at java.lang.reflect.Method.invoke(Native Method)
                                                                                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
                                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
                                                                             Caused by: android.os.TransactionTooLargeException: data parcel size 7991424 bytes
                                                                                at android.os.BinderProxy.transactNative(Native Method)
                                                                                at android.os.BinderProxy.transact(Binder.java:628)
                                                                                at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3563)

更新:

这就是我从位图中获取 Uri 的方式。但是我想使用 getCacheDir() 而不是 getExternalDir()。我怎样才能做到这一点?:

public Uri getBitmapFromDrawable(Bitmap bmp) {

        // Store image to default external storage directory
        Uri bmpUri = null;
        try {
            // Use methods on Context to access package-specific directories on external storage.
            // This way, you don't need to request external read/write permission.
            // See https://youtu.be/5xVh-7ywKpE?t=25m25s
            File file = new File(PhotoDetailActivity.this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
            FileOutputStream out = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.close();

            if (Build.VERSION.SDK_INT >= 24) {
                // wrap File object into a content provider. NOTE: authority here should match authority in manifest declaration
                bmpUri = FileProvider.getUriForFile(PhotoDetailActivity.this, "com.aligntech.myinvisalign.fileprovider", file);  // use this version for API >= 24
            } else {
                bmpUri = Uri.fromFile(file);
            }

            // **Note:** For API < 24, you may use bmpUri = Uri.fromFile(file);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return bmpUri;
    }

This is my logic

The documentation for EXTRA_STREAM表示该值为"content: URI holding a stream of data associated with the Intent"。它没有说该值为 "a Bitmap"。您需要在此 extra 中提供一个 Uri,其他方可以从中获取流(使用 ContentResolver)来获取您的数据。然后,数据需要在你的 Intent 的 MIME 类型中指定的格式,而 Bitmap 没有 MIME 类型(更不用说 wildcard MIME 类型)。

This is how I am getting the Uri from Bitmap. But instead of getExternalDir() I want to use getCacheDir(). How can I achieve that?:

第 1 步:替换:

File file = new File(PhotoDetailActivity.this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");

与:

File file = new File(getCacheDir(), "share_image_" + System.currentTimeMillis() + ".png");

第 2 步:对所有 API 级别使用 FileProvider.getUriForFile(PhotoDetailActivity.this, "com.aligntech.myinvisalign.fileprovider", file);,否则其他应用无法访问您的内容

第 3 步:确保您的 FileProvider 元数据 XML 资源设置有 <cache-path> 元素

第 4 步:在 Intent 的 MIME 类型中使用 image/jpeg(不是通配符),因为您要将此图像另存为 JPEG