Android 安卓4.4中的新警告

Android 安卓4.4中的新警告,android,image,exception,Android,Image,Exception,我最近注意到这些异常(已捕获但已登录到logcat): W/System.err(2612):java.lang.RuntimeException:画布:尝试使用非预乘位图android.graphics。Bitmap@535924e0 W/System.err(2612):位于android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1088) W/System.err(2612):位于android.graphics.Canvas(Canva

我最近注意到这些异常(已捕获但已登录到logcat):

W/System.err(2612):java.lang.RuntimeException:画布:尝试使用非预乘位图android.graphics。Bitmap@535924e0
W/System.err(2612):位于android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1088)
W/System.err(2612):位于android.graphics.Canvas(Canvas.java:139)
System.err(2612):位于com.example.imaging.ImageHelper.addShadow(ImageHelper.java:553)
我试图理解这个异常意味着什么(以及非预乘位图),但我不确定是什么导致了这个异常。我们从服务器获取的图像有问题,还是我们在本地执行的操作有问题?(导致异常的不仅仅是这一行,而是其中之一)

作为参考,我在这里添加了有问题的方法,并突出显示了导致异常的方法:

public static Bitmap addShadow(Bitmap bitmap) {
    try {
        BlurMaskFilter blurFilter = new BlurMaskFilter(12, BlurMaskFilter.Blur.OUTER);
        Paint shadowPaint = new Paint();
        shadowPaint.setMaskFilter(blurFilter);
        shadowPaint.setShadowLayer(12, -3, -3, Color.parseColor("#33000000"));
        int[] offsetXY = new int[2];

        Bitmap shadowImage = bitmap.extractAlpha(shadowPaint, offsetXY);
        Bitmap shadowImage32 = shadowImage.copy(Bitmap.Config.ARGB_8888, true);

        Canvas c = new Canvas(shadowImage32); // exception occurs here <----
        c.drawBitmap(bitmap, -offsetXY[0], -offsetXY[1], null);

        return shadowImage32;
    }  catch (Exception e) {
        e.printStackTrace();
    }
    return bitmap; // if error return the original bitmap

}
公共静态位图addShadow(位图){
试一试{
BlurMaskFilter blurFilter=新的BlurMaskFilter(12,BlurMaskFilter.Blur.OUTER);
绘制阴影绘制=新绘制();
shadowPaint.setMaskFilter(模糊过滤器);
shadowPaint.setShadowLayer(12,-3,-3,Color.parseColor(#33000000));
int[]offsetXY=新的int[2];
位图shadowImage=Bitmap.extractAlpha(shadowPaint,offsetXY);
位图shadowImage32=shadowImage.copy(Bitmap.Config.ARGB_8888,true);

Canvas c=new Canvas(shadowImage32);//这里发生异常我在完全相同的代码中面临完全相同的问题,但我需要在Android代码中解决这个问题,而不是在应用程序外更改图像,因为我使用的是从用户设备加载的图像

在canvas调用之前,我发现了以下内容:

这里的问题是我的最小API级别是10,isPremultiplied()需要API 17,setPremultiplied(true)需要API 19

编辑:我已经使用带有API 10的设备进行了测试,并且没有此类异常,因此我猜在API 19中,他们引入了预乘法处理和异常。因此,最后,我的代码有以下几行:

// Fix the non pre-multiplied exception for API 19+.
if ( android.os.Build.VERSION.SDK_INT >= 19 && !shadowImage32.isPremultiplied() )
{
    shadowImage32.setPremultiplied( true );
}

参考Xavi answer,我使用一个非常旧的代码将此方法(用于支持新设备)称为反射:

if ( android.os.Build.VERSION.SDK_INT >= 19 )
            {
                try {
                    java.lang.reflect.Method method = shadowImage32.getClass().getMethod("setPremultiplied",boolean.class);
                    method.invoke(shadowImage32, true);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
            }

我认为这与拥有一个独特的alpha通道有关,而不是将alpha预乘到颜色组件中,以更直接(从而更有效)地生成格式与实际的显示实现兼容。@ChrisStratton这是否意味着我应该在服务器上更改/重新转换图像,还是应该修改addShadow函数?如果您可以接受,在服务器上更改图像可能是运行时最有效的解决方案。
// Fix the non pre-multiplied exception for API 19+.
if ( android.os.Build.VERSION.SDK_INT >= 19 && !shadowImage32.isPremultiplied() )
{
    shadowImage32.setPremultiplied( true );
}
if ( android.os.Build.VERSION.SDK_INT >= 19 )
            {
                try {
                    java.lang.reflect.Method method = shadowImage32.getClass().getMethod("setPremultiplied",boolean.class);
                    method.invoke(shadowImage32, true);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
            }