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
我正在尝试通过 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