【问题标题】:Android startActivity error when passing (through intent) jpg image file in byteArray, not when passing png image file在byteArray中传递(通过意图)jpg图像文件时Android startActivity错误,而不是传递png图像文件时
【发布时间】:2018-07-13 01:04:43
【问题描述】:

我正在尝试将 jpg 和 png 图像文件从一个活动 (ImageUploadActivity) 发送到另一个活动 (ImageResultActivity)。图像是从图库中选择或从相机拍摄的。

//Select image from gallery
//belongs to ImageUploadActivity

Bitmap bm = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage);
File file = new File("testPic.png");
FileOutputStream fos = openFileOutput("testPic.png" , 0);
bm.compress(Bitmap.CompressFormat.PNG, 50 , fos);
fos.flush();
fos.close();

下面是我尝试发送图像的代码行。 当我传递 PNG 格式时它运行良好,但关于 JPG 格式它返回 RuntimeError 因为 startActivity()。我将这段代码放在 Handler 中,因为我需要在开始新活动之前显示存在的屏幕一段时间。

//belongs to ImageUploadActivity's one button's clicklistener

new Handler().postDelayed(new Runnable() {
    @Override public void run() {
        ByteArrayOutputStream bStream = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 50, bStream);
        byte[] byteArray = bStream.toByteArray();
        Intent i = new Intent(ImageUploadActivity.this,ImageResultActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        i.putExtra("imageArrInput", byteArray);
        startActivity(i);
    }
}, 1500);

这是完整的错误跟踪

07-13 10:10:00.075 3731-3749/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 76)
07-13 10:10:02.254 15346-15346/example.com.samsung.humintec E/aaaa: [B@20377d1
        i.putExtra("imageArrInput", byteArray);
    Stream.flush();
    bStream.close();
07-13 10:10:02.261 15346-15346/example.com.samsung.humintec E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 4512136)
07-13 10:10:02.267 15346-15346/example.com.samsung.humintec E/AndroidRuntime: FATAL EXCEPTION: main
        Process: example.com.samsung.humintec, PID: 15346
        java.lang.RuntimeException: Failure from system
            at android.app.Instrumentation.execStartActivity(Instrumentation.java:1533)
            at android.app.Activity.startActivityForResult(Activity.java:4399)
            at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54)
            at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:65)
            at android.app.Activity.startActivityForResult(Activity.java:4358)
            at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:711)
            at android.app.Activity.startActivity(Activity.java:4682)
            at android.app.Activity.startActivity(Activity.java:4650)
            at example.com.samsung.humintec.Activity.ImageUploadActivity$2.run(ImageUploadActivity.java:119)
            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:6682)
            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 4512136 bytes
            at android.os.BinderProxy.transactNative(Native Method)
            at android.os.BinderProxy.transact(Binder.java:628)
            at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3529)
            at android.app.Instrumentation.execStartActivity(Instrumentation.java:1526)
            at android.app.Activity.startActivityForResult(Activity.java:4399) 
            at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54) 
            at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:65) 
            at android.app.Activity.startActivityForResult(Activity.java:4358) 
            at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:711) 
            at android.app.Activity.startActivity(Activity.java:4682) 
            at android.app.Activity.startActivity(Activity.java:4650) 
            at example.com.samsung.humintec.Activity.ImageUploadActivity$2.run(ImageUploadActivity.java:119) 
            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:6682) 
            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) 

【问题讨论】:

  • 如果您还发布完整的错误跟踪(堆栈跟踪)以及有关这些代码在您的活动中的位置的更多上下文,这将有所帮助。为什么 postDelayed 调用中的第二个代码?
  • @TylerV 正如你所说,我编辑了这个问题。我想稍微展示一下progressBar。

标签: android image android-intent start-activity


【解决方案1】:

你有一个TransactionTooLargeException

避免 TransactionTooLargeException 的关键是保持所有 交易量比较小。尽量减少内存量 需要为参数和返回值创建一个 Parcel 远程过程调用。避免传输大量字符串 或大位图。如果可能,尝试将大请求分解为 小块。

或者你可以在here看到更多

而且我不知道你为什么需要通过意图传递它,因为你可以在第二个活动中得到它。

所以我的解决方案是只发送一个密钥(可能是此图像的名称)并在第二个活动中获取它(使用该密钥),如下所示

发送密钥

new Handler().postDelayed(new Runnable() {
                @Override public void run() {
                    i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                    i.putExtra("image_name", yourImageName);
                    startActivity(i);
                }
            }, 1500);

在第二个活动中:

Bitmap bmp = null;
String filename = getIntent().getStringExtra("image_name");
try {
    FileInputStream is = this.openFileInput(filename);
    bmp = BitmapFactory.decodeStream(is);
    is.close();
} catch (Exception e) {
    e.printStackTrace();
}

希望对你有帮助

【讨论】:

  • 非常感谢,现在我注意到我忽略了一些重要的事情,即意图不适合大型对象。
【解决方案2】:

Intent 不适合传递大对象,因为 Intent 会序列化和反序列化对象,这对于大对象来说并不容易。

如果你的项目使用 EventBus,你可以通过 EventBus 传递你的图像对象,因为 EventBus 只传递一个对象的引用。

如果你不想使用 EventBus 或者你想做进程间传递(EventBus 不能),那么@GianhTran 的方式,即将图像保存为非 ui 线程中的文件并读取您新开始的活动中的图片将是一个选择。

【讨论】:

  • 也非常感谢,您给了我很好的建议,我会记住这一点。希望我能在某个地方正确使用 EventBus。
猜你喜欢
  • 2013-08-30
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多