2
votes

I have a custom Android device with an LCD screen. It can draw bitmaps. I prepare them from Android views.

private Bitmap loadBitmapFromView() {
    if ((mView.getVisibility() != VISIBLE) ||
            (mView.getMeasuredWidth() <= 0) ||
            (mView.getMeasuredHeight() <= 0)) return null;
    Bitmap b;
    if ((mView instanceof ImageView) && !(mView instanceof ImageButton)) {
        BitmapDrawable drawable = ((BitmapDrawable) ((ImageView) mView).getDrawable());
        if (drawable == null) return null;
        b = Bitmap.createScaledBitmap(drawable.getBitmap().copy(drawable.getBitmap().getConfig(), true),
                mView.getMeasuredWidth(), mView.getMeasuredHeight(), false);
    } else {
        b = Bitmap.createBitmap(mView.getMeasuredWidth(), mView.getMeasuredHeight(), ARGB_8888);
    }
    replaceColor(b, ColorChannel.ALPHA, 0, mBackgroundColor);
    Canvas c = new Canvas(b);
    mView.layout(mLocation.x - mParentLocation.x, mLocation.y - mParentLocation.y,
            mLocation.x - mParentLocation.x + mView.getMeasuredWidth(),
            mLocation.y - mParentLocation.y + mView.getMeasuredHeight());
    mView.draw(c);
    return b;
}

ARGB_8888 used here because some views have transparency.

After some time of usage, it stops to draw.

I added android:largeHeap="true" and android:hardwareAccelerated="false" to Manifest and got OOM

12-17 11:19:32.591 15169-15169/com.appcard.androidterminal E/art: Throwing OutOfMemoryError "Failed to allocate a 614412 byte allocation with 4194304 free bytes and 244MB until OOM"
12-17 11:19:32.619 15169-15169/com.appcard.androidterminal E/Surface: dequeueBuffer failed (Function not implemented)
12-17 11:19:32.620 15169-15169/com.appcard.androidterminal E/ViewRootImpl: Could not lock surface
    java.lang.IllegalArgumentException
        at android.view.Surface.nativeLockCanvas(Native Method)
        at android.view.Surface.lockCanvas(Surface.java:264)
        at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:2998)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2966)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2753)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2367)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1292)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6598)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:800)
        at android.view.Choreographer.doCallbacks(Choreographer.java:603)
        at android.view.Choreographer.doFrame(Choreographer.java:572)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:786)
        at android.os.Handler.handleCallback(Handler.java:815)
        at android.os.Handler.dispatchMessage(Handler.java:104)
        at android.os.Looper.loop(Looper.java:194)
        at android.app.ActivityThread.main(ActivityThread.java:5643)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

I tried to recycle bitmap after drawing, but it doesn't help.

3

3 Answers

1
votes

This is because of memory limitations. You can load scaled down version of your bitmap.

Follow documentation here to know more about how to efficiently load bitmaps

https://developer.android.com/topic/performance/graphics/load-bitmap

0
votes

I solved OutOfMemory issues by replacing imageView.setImageBitmap(bitmap) and imageView.setImageResource(imageRes) with Glide: https://bumptech.github.io/glide/doc/targets.html

0
votes

Try using

Bitmap bitmap = Bitmap.createScaledBitmap(view.getDrawingCache(), width, height, false);

Here view is the view that you want to draw, width and height are the output width and height.

If the problem still persist, you may reduce the size of the bitmap by a factor of 2 or so. Secondly if you are handling multiple bitmaps, you may do it one by one so that there are only one or two bitmaps in the memory that are really required.