OpenGL random crash on Honeycomb with Hardware Acc

2019-05-18 15:16发布

问题:

I am experiencing a big probleme on Android Honeycomb 3.0 (Acer Iconia). I don't use any openGL view, I only set in the manifest

android:hardwareAccelerated="true"

The fact is that when I load a view with a certain amount of pictures, and I change its content and background several times on clicking on a button, my intent finishes and the previous intent appears. I thinks I well manage memory. This message appears when it appends:

06-22 10:13:53.510: ERROR/libEGL(951): call to OpenGL ES API with no current context (logged once per thread)
06-22 10:14:03.150: ERROR/InputDispatcher(113): channel '4098b530 com.mycompany.myapp/com.mycompany.myapp.FolderActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x8
06-22 10:14:03.150: ERROR/InputDispatcher(113): channel '4098b530 com.mycompany.myapp/com.mycompany.myapp.FolderActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
06-22 10:14:03.150: ERROR/InputDispatcher(113): channel '409d30e0 com.mycompany.myapp/mycompany.myapp.GalleryActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x8
06-22 10:14:03.150: ERROR/InputDispatcher(113): channel '409d30e0 com.mycompany.myapp/mycompany.myapp.GalleryActivity (server)' ~ Channel is unrecoverably broken and will be disposed!

When I set this I have no crash, but it's very laggy:

android:hardwareAccelerated="false"

回答1:

Ok guys, I found the solution :) I updated my tab to Android 3.1, that gave me the real error, OutOfMemoryError. I was allocating my background on a button click. So I now make a

WeakReference<BitmapDrawable>

instead of BitmapDrawable and disable my button until the background is well set (in order to avoid two big BitmapDrawable creation at the same time).

Hoping it will help you, poor 3.0 developpers ^^

Edit: Here is a class I created to manage cache:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.drawable.BitmapDrawable;

public class BitmapDrawableCache {

    private static BitmapDrawableCache                 instance = null;
    WeakHashMap<String, WeakReference<BitmapDrawable>> cache;

    private BitmapDrawableCache() {
        cache = new WeakHashMap<String, WeakReference<BitmapDrawable>>();
    }

    public synchronized static BitmapDrawable get(String drawablePath) {
        if (instance == null) {
            instance = new BitmapDrawableCache();
        }

        BitmapDrawable bmd = null;
        WeakReference<BitmapDrawable> wr0 = instance.cache.get(drawablePath);
        if (instance.cache.get(drawablePath) != null) bmd = wr0.get();

        if (bmd == null) {
            WeakReference<BitmapDrawable> wr = new WeakReference<BitmapDrawable>(new BitmapDrawable(drawablePath));
            instance.cache.put(drawablePath, wr);
            bmd = wr.get();
        }

        return bmd;

    }

    public synchronized static BitmapDrawable get(Bitmap bitmap) {

        String drawableName = "_bitmap_" + bitmap.hashCode();

        if (instance == null) {
            instance = new BitmapDrawableCache();
        }

        BitmapDrawable bmd = null;
        WeakReference<BitmapDrawable> wr0 = instance.cache.get(drawableName);
        if (instance.cache.get(drawableName) != null) bmd = wr0.get();

        if (bmd == null) {
            WeakReference<BitmapDrawable> wr = new WeakReference<BitmapDrawable>(new BitmapDrawable(bitmap));
            instance.cache.put(drawableName, wr);
            bmd = wr.get();
        }

        return bmd;

    }


    //Get BitmapDrawable in cache with options to reduce its size
    public synchronized static BitmapDrawable get(String drawableName, Options options) {
        if (instance == null) {
            instance = new BitmapDrawableCache();
        }

        BitmapDrawable bmd = null;
        WeakReference<BitmapDrawable> wr0 = instance.cache.get(drawableName);
        if (instance.cache.get(drawableName) != null) bmd = wr0.get();

        if (bmd == null) {
            File f = new File(drawableName);
            WeakReference<BitmapDrawable> wr = new WeakReference<BitmapDrawable>(new BitmapDrawable(instance.decodeFile(f, options)));
            instance.cache.put(drawableName, wr);
            bmd = wr.get();
        }

        return bmd;

    }  


  //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f, Options o2){
        try {
            //Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            int scale=1;
            //The new size we want to scale to
            final int REQUIRED_SIZE=70;

            //Find the correct scale value. It should be the power of 2.
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //Decode with inSampleSize
           // BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }

}