2011年9月10日土曜日

java.lang.OutOfMemoryError: bitmap size exceeds VM budget【android】【画像表示】【エラー】

下記にこの記事の内容に関連する記事があります。ご参考ください。
⇒画像を画面サイズに合わせる(縮尺・縮小する)



カメラで撮影した画像のような高画質な画像を表示すると、たびたび下記のような
メッセージが出力され、アプリケーションが強制終了してしまいます。


09-10 06:27:57.701: ERROR/dalvikvm-heap(2168): 7680000-byte external allocation too large for this process.
09-10 06:27:57.701: ERROR/GraphicsJNI(2168): VM won't let us allocate 7680000 bytes
09-10 06:27:57.712: DEBUG/skia(2168): --- decoder->decode returned false
09-10 06:27:57.732: DEBUG/AndroidRuntime(2168): Shutting down VM
09-10 06:27:57.732: WARN/dalvikvm(2168): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): FATAL EXCEPTION: main
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:459)
09-10 06:27:57.941: ERROR/AndroidRuntime(2168): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:271)

※EclipseのDDMSのLogCatにLogは表示されています。


この場合の対処方法として、下記のようなものがあげられます。
 ・Bitmap.Configの設定をARGB_8888をやめて、RGB_565やARGB_4444を使用する(デフォルトRGB_565)
  これらは解像度の設定。
 ・inSampleSizeを設定し、画像ファイルのサイズを小さくして表示する。

  BitmapFactory.Options bmfOptions = new BitmapFactory.Options();
  bmfOptions.inSampleSize = 4;

  とすると、1辺4分の1のサイズとなり、面積は16分の1。

 ・システムメモリ上に再利用性の無いオブジェクトがある場合に勝手に解放するように設定する。
  bmfOptions.inPurgeable = true;

 ・ビットマップのサイズを現在の表示メトリクスに合わせる。
  DisplayMetrics dm = this.getResources().getDisplayMetrics();
  bmfOptions.inDensity = dm.densityDpi;

 ・使わなくなったタイミングでBitmapデータの解放を行う。
  Bitmap.recycle();
  ※Bitmap変数をクラス変数として持ち、onPause()メソッドでBitmap.recycle();
   とすればよいですが、System.gc()でよい気もします。

 ・ガーベッジコレクションを行う。
  System.gc();


ざっとこんなところですが、Bitmap.recycle()は使用したことがないので、情報いただければ幸いです。



私は今のところ下記のような対処を行い、OutOfMemoryErrorを防いでいます。
(不要な処理もありかもしれません)

①ビットマップ設定メソッドで、BitmapFactory.Optionsの設定を行う。
    /**
* ディレクトリリストに表示するBitmapを設定する。
* @param File file(設定するBitmapファイル)
* @return Bitmap bmImage(設定されたBitmap)
* @exception なし
*/

private Bitmap setBitmap(File file){

// ビットマップ作成オブジェクトの設定
BitmapFactory.Options bmfOptions = new BitmapFactory.Options();
// ARGBでそれぞれ0~127段階の色を使用(メモリ対策)
bmfOptions.inPreferredConfig = Config.ARGB_4444;
// 画像を1/20サイズに縮小(メモリ対策)
bmfOptions.inSampleSize = 20;
// システムメモリ上に再利用性の無いオブジェクトがある場合に勝手に解放(メモリ対策)
bmfOptions.inPurgeable = true;
// 現在の表示メトリクスの取得
DisplayMetrics dm = this.getResources().getDisplayMetrics();
// ビットマップのサイズを現在の表示メトリクスに合わせる(メモリ対策)
bmfOptions.inDensity = dm.densityDpi;
// 画像ファイルオブジェクトとビットマップ作成オブジェクトから、ビットマップオブジェクト作成
Bitmap bmImage = BitmapFactory.decodeFile(file.getPath(),bmfOptions);

return bmImage;
}

 

②アプリケーション終了時(戻るボタン押下時など)にSystem.gc();を行う。
 ※次回、Activityのライフサイクルも含めて説明します。



日本Androidの会がOutOfMemoryErrorについて纏めてくださっております。
http://mtnk.org/down/PDF/OutOfMemoryError.pdf

0 件のコメント:

コメントを投稿