【問題】
ICS(Android 4.0)では問題なく動いていたのにJB(Android 4.1, 4.2)では突然エラーで落ちるようになった。LogCatではjava.lang.IllegalArgumentException: Cannot draw recycled bitmaps
とか出ているんですけど。
【結論】
Jelly BeanでBitmap.createScaledBimapで等倍(オリジナルと同じサイズ)にスケーリングすると、コピーされた画像が渡されるのではなく参照渡しになる。例えば…
scaledImg = Bitmap.createScaledBitmap(orgImg
, newWidth, newHeight, true);
if (orgImg != null){ // メモリ節約のため元々の画像を削除
orgImg.recycle();
orgImg = null;
}
imageView.setImageBitmap(scaledImg); // サイズを変えた画像を表示
ここで、newWidthとnewHeightが元々のorgImgと同じサイズの場合、Jelly Beanでのみ参照渡しになり、recycleされたorgImgを最後の行で表示しようとしてエラーが発生、アプリごと落ちてしまう。
なので、1行目を
if (orgImg.getWidth() == newWidth
&& orgImg.getHeight() == newHeight)
scaledImg = orgImg.copy(orgImg.getConfig(), true);
else
scaledImg = Bitmap.createScaledBitmap(orgImg,
newWidth, newHeight, true);
の様に変更してあげて、等倍コピーの場合は、単純に画像のコピーを意図的に渡してあげるようにするといい感じ。
【ごにょごにょ…】
これって、限りなくバグじゃねー!?って思うわけですよ。でも、ここで愚痴っても世の中に出たAndroid製品が変わるわけでもなく、粛々と対応するしか無いんですよね。一方で、Androidのドキュメントには
If the specified width and height are the same as the current width and height of the source btimap, the source bitmap is returned and now new bitmap is created.
(最後のnow new bitmap is createdはNO new bitmap...の誤記であろう)
と明記されている。なので、本気でこの仕様にしたのであろう。迷惑な話だ。
【エラーログ】
こんな感じのエラーが出ておりました…W/System.err(23698): java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
W/System.err(23698): at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:794)
W/System.err(23698): at android.view.GLES20RecordingCanvas.drawBitmap(GLES20RecordingCanvas.java:117)
W/System.err(23698): at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)
W/System.err(23698): at android.widget.ImageView.onDraw(ImageView.java:979)
W/System.err(23698): at android.view.View.draw(View.java:13650)
W/System.err(23698): at android.view.View.getDisplayList(View.java:12601)
W/System.err(23698): at android.view.View.getDisplayList(View.java:12645)
【参考リンク】
https://jira.appcelerator.org/browse/TC-1143先駆者の方には、本当に感謝感謝です…
0 件のコメント:
コメントを投稿