Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.IllegalStateException: Software rendering doesn't support hardware bitmaps

Tags:

android

I need to get the screenshot of a View. I have tried two methods to do this work. Unfortunately, both result in the same bug.

Here is the log:

java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps
at android.graphics.BaseCanvas.null onHwBitmapInSwMode(null)(BaseCanvas.java:550)
at android.graphics.BaseCanvas.null throwIfHwBitmapInSwMode(null)(BaseCanvas.java:557)
at android.graphics.BaseCanvas.null throwIfCannotDraw(null)(BaseCanvas.java:69)
at android.graphics.BaseCanvas.null drawBitmap(null)(BaseCanvas.java:127)
at android.graphics.Canvas.null drawBitmap(null)(Canvas.java:1504)
at android.graphics.drawable.BitmapDrawable.null draw(null)(BitmapDrawable.java:545)
at android.widget.ImageView.null onDraw(null)(ImageView.java:1355)
at android.view.View.null draw(null)(View.java:20248)
at android.view.View.null draw(null)(View.java:20118)
at android.view.ViewGroup.null drawChild(null)(ViewGroup.java:4336)
at android.view.ViewGroup.null dispatchDraw(null)(ViewGroup.java:4115)
at android.view.ViewOverlay$OverlayViewGroup.null dispatchDraw(null)(ViewOverlay.java:251)
at android.view.View.null draw(null)(View.java:20251)
at android.view.View.null buildDrawingCacheImpl(null)(View.java:19516)
at android.view.View.null buildDrawingCache(null)(View.java:19379)
at android.view.View.null getDrawingCache(null)(View.java:19215)
at android.view.View.null getDrawingCache(null)(View.java:19166)
at com.omnipotent.free.videodownloader.pro.utils.ViewUtils.android.graphics.Bitmap captureView(android.view.View)(ViewUtils.java:70)
at com.omnipotent.free.videodownloader.pro.ui.main.MainActivity.com.omnipotent.free.videodownloader.pro.data.bean.TabBean getCurrentTabsData()(MainActivity.java:325)
at com.omnipotent.free.videodownloader.pro.ui.main.MainActivity.com.omnipotent.free.videodownloader.pro.data.bean.TabBean access$getCurrentTabsData(com.omnipotent.free.videodownloader.pro.ui.main.MainActivity)(MainActivity.java:84)
at com.omnipotent.free.videodownloader.pro.ui.main.MainActivity$onAddTab$1.void run()(MainActivity.java:628)
at android.os.Handler.null handleCallback(null)(Handler.java:873)
at android.os.Handler.null dispatchMessage(null)(Handler.java:99)
at android.os.Looper.null loop(null)(Looper.java:193)
at android.app.ActivityThread.null main(null)(ActivityThread.java:6936)
at java.lang.reflect.Method.null invoke(null)(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.null run(null)(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.null main(null)(ZygoteInit.java:870)

I have examined the code carefully and looked up related articles on the Internet. I, however, have not solved it yet, which really make me feel frustrating. This bug has only happened above android O.

Here are two methods that I have tried:

Method1:

public static Bitmap captureView(View view) {
    Bitmap tBitmap = Bitmap.createBitmap(
            view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
    Canvas canvas = new Canvas(tBitmap);
    view.draw(canvas);
    canvas.setBitmap(null);
    return tBitmap;
}

Method2:

public static Bitmap captureView(View view) {

    if (view == null) return null;
    boolean drawingCacheEnabled = view.isDrawingCacheEnabled();
    boolean willNotCacheDrawing = view.willNotCacheDrawing();
    view.setDrawingCacheEnabled(true);
    view.setWillNotCacheDrawing(false);
    final Bitmap drawingCache = view.getDrawingCache();
    Bitmap bitmap;
    if (null == drawingCache) {
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        bitmap = Bitmap.createBitmap(view.getDrawingCache());
    } else {
        bitmap = Bitmap.createBitmap(drawingCache);
    }
    view.destroyDrawingCache();
    view.setWillNotCacheDrawing(willNotCacheDrawing);
    view.setDrawingCacheEnabled(drawingCacheEnabled);
    return bitmap;
}

What need to be mentioned is that I have set android:hardwareAccelerated="true" for my Activity, where I invoked captureView method.

like image 363
wang willway Avatar asked Sep 11 '25 17:09

wang willway


2 Answers

Read Glide hardware bitmap docs, and find PixelCopy class, which may solve this bug.

Use PixelCopy to convert view to Bitmap above Android O, and use previous method below Android O.

Here is my code:

fun captureView(view: View, window: Window, bitmapCallback: (Bitmap)->Unit) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // Above Android O, use PixelCopy
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val location = IntArray(2)
        view.getLocationInWindow(location)
        PixelCopy.request(window,
            Rect(location[0], location[1], location[0] + view.width, location[1] + view.height),
            bitmap,
            {
                if (it == PixelCopy.SUCCESS) {
                    bitmapCallback.invoke(bitmap)
                }
            },
            Handler(Looper.getMainLooper()) )
    } else {
        val tBitmap = Bitmap.createBitmap(
            view.width, view.height, Bitmap.Config.RGB_565
        )
        val canvas = Canvas(tBitmap)
        view.draw(canvas)
        canvas.setBitmap(null)
        bitmapCallback.invoke(tBitmap)
    }
}

The shortage is that I have to use a callback, which I don't like very much.

Hope that it works.

like image 74
wang willway Avatar answered Sep 13 '25 05:09

wang willway


you can try copying hardware type bitmap to your desired type bitmap,e.g:

Bitmap targetBmp = originBmp.copy(Bitmap.Config.ARGB_8888, false);
like image 35
Liang Lu Avatar answered Sep 13 '25 07:09

Liang Lu