-1

I am getting the following error when passing a byte array from one activity to another through an intent. I'm not sure whether its because the array is too large, or if its something else. Here is the error:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.roshan.android.picscheduler, PID: 19689
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.roshan.android.picscheduler/com.roshan.android.picscheduler.ImageDetectActivity}: java.lang.NullPointerException: Attempt to get length of null array
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2955)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030)
    at android.app.ActivityThread.-wrap11(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
 Caused by: java.lang.NullPointerException: Attempt to get length of null array
    at com.roshan.android.picscheduler.ImageDetectActivity.onCreate(ImageDetectActivity.java:40)
    at android.app.Activity.performCreate(Activity.java:7183)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1220)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2908)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030) 
    at android.app.ActivityThread.-wrap11(Unknown Source:0) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696) 
    at android.os.Handler.dispatchMessage(Handler.java:105) 
    at android.os.Looper.loop(Looper.java:164) 
    at android.app.ActivityThread.main(ActivityThread.java:6938) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) 

In the main activity, I have this code:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);

    mCameraView.setCameraListener(new CameraKitView.CameraListener() {
        @Override
        public void onOpened() {

        }

        @Override
        public void onClosed() {

        }
    });

    mCameraButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View view) {

            mCameraView.captureImage(new CameraKitView.ImageCallback() {
                @Override
                public void onImage(CameraKitView cameraKitView, byte[] bytes) {
                    imageBytes = bytes;

                }
            });



            Intent intent = new Intent(MainActivity.this.getApplicationContext(), ImageDetectActivity.class);
            intent.putExtra("CapturedImage", imageBytes);
            intent.putExtra("width", mCameraView.getWidth());
            intent.putExtra("height", mCameraView.getHeight());
            startActivity(intent);

            //TODO: Launch new activity, pass the bitmap
            // Maybe use Fragments instead of new activity?
        }
    });
}

In the target activity's onCreate method, I have this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_image_detect);

    intent = getIntent();
    imageBytes = intent.getByteArrayExtra("CapturedImage");
    cameraWidth = intent.getIntExtra("width", 0);
    cameraHeight = intent.getIntExtra("height", 0);

    bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
    bitmap = Bitmap.createScaledBitmap(bitmap, cameraWidth, cameraHeight, false);

    image = FirebaseVisionImage.fromBitmap(bitmap);
    detector = FirebaseVision.getInstance().getOnDeviceTextRecognizer();

    result = detector.processImage(image)
            .addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
                @Override
                public void onSuccess(FirebaseVisionText firebaseVisionText) {
                    String resultText = firebaseVisionText.getText();
                    Log.d("TEST", resultText);
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {

                }
            });
}

The error is thrown as soon as I try to decode the byte array, which I assume means it receiving a null array.

Roshan
  • 55
  • 1
  • 6

2 Answers2

0

The error is happening because the byte array you are getting from the intent is null.

Possible reasons:

1. You passed a null byte array from the original Activity.

2. You didn't use the exact same String when adding an extra to the intent, and then getting it back from the intent.

I would suggest debugging your code, a lot of NullPointerExceptions can be resolved by a simple debug.

Daniel B.
  • 2,491
  • 2
  • 12
  • 23
  • I've figured out that its because the byte array is null, but I'm not sure why or how to fix it. When I code it to do what I need it to do within the same activity, it works, but when I try and pass the byte array through an intent to a different activity, it passes null. – Roshan Jan 01 '19 at 17:55
  • 1
    @Roshan please provide the full code of both activities – Daniel B. Jan 01 '19 at 18:11
  • @Daneil B, I edited the post to include all the code – Roshan Jan 01 '19 at 18:19
0

This callback

mCameraView.captureImage(new CameraKitView.ImageCallback() {
    @Override
    public void onImage(CameraKitView cameraKitView, byte[] bytes) {
        imageBytes = bytes;
    }
});

is called asynchronous. That means if you want to add the bytes to the intent, you need to move the intent code into that callback.

The complete onClick call would need to be changed to this:

mCameraButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View view) {

        mCameraView.captureImage(new CameraKitView.ImageCallback() {
            @Override
            public void onImage(CameraKitView cameraKitView, byte[] bytes) {
                imageBytes = bytes;

                Intent intent = new Intent(MainActivity.this.getApplicationContext(), ImageDetectActivity.class);
                intent.putExtra("CapturedImage", imageBytes);
                intent.putExtra("width", mCameraView.getWidth());
                intent.putExtra("height", mCameraView.getHeight());
                startActivity(intent);
            }
        });
    }
});

This might fix your problem with passing the byte to the next activity but this code also might cause a lag between the user interaction (the click) and "stuff" happening on the UI so the user will feel a lag. You should consider improving that (but this is outside of the scope of this question)

WarrenFaith
  • 57,492
  • 25
  • 134
  • 150
  • Thank you, this worked! I swear I tried it and it still caused the app to crash, but I just tried it again and it worked fine. – Roshan Jan 01 '19 at 18:33