R

Recee Crash Diagnostics

Firestore live log stream · app_logs

Connecting…

Total logs captured

0

Unique users

0

Fatal crashes

0

Upload failures

0

Active devices

0

Crashes by Device Model

Top 8 devices by crash count (APP_CRASH + UPLOAD_CRASH_OOM)

RAM Available at Crash Time

Last 20 crash events vs. 200 MB critical threshold

Upload Step Timeline

Last 30 UPLOAD_* events, oldest → newest. Hover a bar for device/RAM/file details.

Permission Requests

Accepted vs. rejected, per permission type (location, notifications). Camera is handled natively by image_picker and isn't logged yet.

Total requests

0

Accepted

0

Rejected

0

Permission Accepted Rejected
No permission events logged yet.

Users by App Version

Latest app version seen per user, from their most recent log entry.

User Role App Version Device RAM Storage Last Seen
Waiting for data…

Detailed Log Stream

Time User Role Device Event Status Message RAM (free/total) File (MB) Details
Waiting for data…

✅ Recommended Fix for Vivo Y19

Downsample bitmaps before they ever hit the heap, instead of decoding full resolution and hoping GC keeps up.

Code Fix — Java

public static Bitmap decodeSampledBitmap(
        String path, int reqWidth, int reqHeight) {

    // 1) Decode bounds only — no pixels allocated yet.
    final BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, opts);

    // 2) Compute the largest inSampleSize that still produces
    //    an image >= the requested dimensions.
    opts.inSampleSize =
        calculateInSampleSize(opts, reqWidth, reqHeight);

    // 3) Decode the actual (downsampled) bitmap.
    opts.inJustDecodeBounds = false;
    opts.inPreferredConfig = Bitmap.Config.RGB_565; // 2 bytes/px
    return BitmapFactory.decodeFile(path, opts);
}

private static int calculateInSampleSize(
        BitmapFactory.Options opts, int reqW, int reqH) {
    final int height = opts.outHeight;
    final int width  = opts.outWidth;
    int inSampleSize = 1;

    if (height > reqH || width > reqW) {
        final int halfHeight = height / 2;
        final int halfWidth  = width / 2;

        while ((halfHeight / inSampleSize) >= reqH
                && (halfWidth / inSampleSize) >= reqW) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

// Usage before upload:
Bitmap upload = decodeSampledBitmap(imagePath, 1600, 1600);
// -> compress to JPEG (quality ~80) into a temp file,
//    upload that file, then recycle() the bitmap.

Why this fixes it

A modern phone camera shot (e.g. 4000×3000) decoded at ARGB_8888 (4 bytes/px) needs ~48 MB for one uncompressed bitmap in RAM. A Vivo Y19 ships 4 GB total RAM, but the app's actual Dalvik/ART heap ceiling is typically 192–256 MB — so 1–2 full-res photos in flight during a Recee submission is enough to trigger OutOfMemoryError, especially alongside the OS, camera preview, and upload buffers already holding memory.

  • inSampleSize decodes directly at a lower resolution — the full-size bitmap is never allocated at all.
  • RGB_565 halves per-pixel memory (2 vs 4 bytes) for photos where alpha isn't needed.
  • Cap the target size to what the upload actually needs (e.g. 1600×1600) — field photos don't need to be uploaded at sensor resolution.
  • Call bitmap.recycle() immediately after the compressed file is written, don't wait for GC.
  • Process one image at a time in the upload queue — never decode multiple full photos concurrently on a 4 GB device.
  • Longer term: replace manual BitmapFactory calls with Glide/Coil, which already downsample and pool bitmaps automatically.