Search code examples
androidcrashchaquopy

app crashes in device but not in emulator while using chaquopy


I created a face detection using chaquopy in android studio. When I ran app into emulator, it's perectly working. But when I lauch in my phone, it crashed. In Run this is shown

I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
I/Toast: Show toast from OpPackageName:com.example.chaquopy, PackageName:com.example.chaquopy
V/BoostFramework: BoostFramework() : mPerf = com.qualcomm.qti.Performance@57230c5
I/Adreno: BLTLIB: Semaphore Timeout, disabling MT
I/Adreno: BLTLIB: Semaphore Timeout count 1
I/Adreno: BLTLIB: Semaphore Timeout count 2
I/Adreno: BLTLIB: Semaphore Timeout count 3
I/Adreno: BLTLIB: Semaphore Timeout count 4
I/Adreno: BLTLIB: Semaphore Timeout count 5
I/Adreno: BLTLIB: Semaphore Timeout count 6
I/Adreno: BLTLIB: Semaphore Timeout count 7
I/art: Waiting for a blocking GC Alloc
I/art: Starting a blocking GC Alloc
    Starting a blocking GC Alloc
I/art: Alloc partial concurrent mark sweep GC freed 220(9KB) AllocSpace objects, 1(480KB) LOS objects, 8% free, 171MB/187MB, paused 262us total 14.558ms
    Starting a blocking GC Alloc
I/art: Starting a blocking GC Alloc
I/art: Alloc concurrent mark sweep GC freed 27(752B) AllocSpace objects, 0(0B) LOS objects, 8% free, 171MB/187MB, paused 237us total 25.550ms
    Forcing collection of SoftReferences for 35MB allocation
    Starting a blocking GC Alloc
I/art: Alloc concurrent mark sweep GC freed 2(48B) AllocSpace objects, 0(0B) LOS objects, 8% free, 171MB/187MB, paused 230us total 24.816ms
W/art: Throwing OutOfMemoryError "Failed to allocate a 36742016 byte allocation with 16777216 free bytes and 20MB until OOM"
I/art: Starting a blocking GC Alloc
    Starting a blocking GC Alloc
I/art: Starting a blocking GC Alloc
I/art: Alloc partial concurrent mark sweep GC freed 4(96B) AllocSpace objects, 0(0B) LOS objects, 8% free, 171MB/187MB, paused 430us total 22.384ms
    Starting a blocking GC Alloc
I/art: Alloc concurrent mark sweep GC freed 2(48B) AllocSpace objects, 0(0B) LOS objects, 8% free, 171MB/187MB, paused 333us total 35.743ms
    Forcing collection of SoftReferences for 35MB allocation
    Starting a blocking GC Alloc
I/art: Alloc concurrent mark sweep GC freed 3(72B) AllocSpace objects, 0(0B) LOS objects, 8% free, 171MB/187MB, paused 249us total 28.176ms
    Starting a blocking GC HomogeneousSpaceCompact
I/art: HomogeneousSpaceCompact marksweep + semispace GC freed 0(0B) AllocSpace objects, 0(0B) LOS objects, 8% free, 171MB/187MB, paused 29.551ms total 29.551ms
W/art: Throwing OutOfMemoryError "Failed to allocate a 36742016 byte allocation with 16777216 free bytes and 20MB until OOM"
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.chaquopy, PID: 32703
    java.lang.OutOfMemoryError: Failed to allocate a 36742016 byte allocation with 16777216 free bytes and 20MB until OOM
        at java.lang.StringFactory.newStringFromChars(StringFactory.java:218)
        at java.lang.StringFactory.newStringFromBytes(StringFactory.java:203)
        at java.lang.StringFactory.newStringFromBytes(StringFactory.java:63)
        at android.util.Base64.encodeToString(Base64.java:456)
        at com.example.chaquopy.MainActivity.getStringImage(MainActivity.java:102)
        at com.example.chaquopy.MainActivity.access$000(MainActivity.java:31)
        at com.example.chaquopy.MainActivity$1.onClick(MainActivity.java:76)
        at android.view.View.performClick(View.java:5619)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
        at android.view.View$PerformClick.run(View.java:22298)
        at android.os.Handler.handleCallback(Handler.java:754)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:165)
        at android.app.ActivityThread.main(ActivityThread.java:6375)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802)
W/AndroidRuntime: finished raiseRlimit, rlim_cur:4096  rlim_max:4096

my code is

 Submitbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"Submit Button is clicked",Toast.LENGTH_SHORT).show();
                //by clicking get image from image view
                bitmapDrawable = (BitmapDrawable) selectedImage.getDrawable();
                bitmap = bitmapDrawable.getBitmap();
                imageString = getStringImage(bitmap);
                //in imageString we get encoded image
                //passing the string into python script
                PyObject pyObject = py.getModule("scripts");
                PyObject obj = pyObject.callAttr("main", imageString);
                //converted to string
                String string = obj.toString();
                //converted to byte array
                byte data[] = android.util.Base64.decode(string,0);
                //converted to bitmap
                Bitmap returnBitmap = BitmapFactory.decodeByteArray(data,0,data.length);

                //now set bitmap to image view
                selectedImage.setImageBitmap(returnBitmap);

            }
        });

and

private String getStringImage(Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG,100,byteArrayOutputStream);
        //storing in byte array
        byte[] imageBytes = byteArrayOutputStream.toByteArray();
        //encoding string
        String encodedImage = android.util.Base64.encodeToString(imageBytes, 0);
        return encodedImage;
    }

In my code when user click submitbtn the image from imageview will encoded into string and send into the python module. then In python script after doing face detection it return again string and in main I do the rest. What can I do?


Solution

  • There's no need to use Base64 here. Just pass the byte[] array to Python directly, and receive it in Python using one of the methods shown in this FAQ.

    Likewise when returning an image from Python, you should return a bytes object, and convert it to a byte[] array using toJava, as shown in the chaquopy-matplotlib example.

    Also, if your image is 36 MB as a PNG, then I assume it's a high-resolution photograph, so you should probably use the JPG format instead.