2回目にビットマップを作成した後、次のエラーが発生します。
04-17 18:28:09.310: ERROR/AndroidRuntime(3458): Java.lang.OutOfMemoryError: bitmap size exceeds VM budget
this._profileBitmap = Bitmap.createBitmap(_profileBitmap, xCoor, yCoor, width, height);
ログから:
04-17 18:27:57.500: INFO/CameraCropView(3458): Original Photo Size: W 1536 x H 2048
04-17 18:28:06.170: INFO/CameraCropView(3458): xCoor: 291
04-17 18:28:06.170: INFO/CameraCropView(3458): yCoor: 430
04-17 18:28:06.170: INFO/CameraCropView(3458): Width: 952
04-17 18:28:06.170: INFO/CameraCropView(3458): Height: 952
画像が大きいのでエラーになります。しかし興味深いのは、最初にエラーが発生せず、2回目に写真を撮ったときにのみ発生することです。このため、このprofileBitmapは破棄されていません。これをどのようにクリーンアップしますか?
私は同じ問題を抱えており、このように修正しました:
私のアプリのサイズは〜18MBで、空きメモリがどれだけ残っているかを確認すると、654KB(1GB RAMで!)のショックを受けました。だから私はプロジェクトからほぼすべての画像を削除し、最初の起動時にインターネットからダウンロードし、必要に応じてSDカードからの写真を使用しました。
アプリの使用量の合計/空きメモリを確認するには:
Runtime.getRuntime().totalMemory();
Runtime.getRuntime().freeMemory();
編集:私は主なことを忘れました-あなたのマニフェストに、アプリケーションタグの間に次の行を追加してください:
Android:largeHeap="true"
Androidのビットマップでのメモリ例外には多くの問題があり、その多くはstackoverflowで説明されています。既存の質問を調べて、既存の質問の1つと一致するかどうかを確認し、一致しない場合は、状況の違いを書いておくとよいでしょう。
いくつかの例:
など: https://stackoverflow.com/search?q=Android+out+of+memory+exception+bitmap
Androidアプリケーションでメモリ不足の例外を回避できるヒントを次に示します。
2。アクティビティが終了したとき。 HEAP DUMP(Android studioのメモリ分析ツール))を確認します。
終了したアクティビティからのHEAP DUMPにオブジェクトがある場合、メモリリークが発生します。コードを確認し、メモリリークの原因を特定します。
今inSampleSizeとは何ですか? inSampleSizeの助けを借りて、実際には、サブサンプル画像ではなく、メモリ内のすべてのピクセルを取得しないようにデコーダーに指示しています。これにより、元の画像よりも少ない数のピクセルがメモリに読み込まれます。元の画像から4ピクセルごとまたは2ピクセルごとにグラブするようにデコーダーに指示できます。 inSampleSizeが4の場合、デコーダは元の画像のピクセル数の1/16の画像を返します。
どれだけのメモリを節約できましたか?計算:)
メモリにロードする前にビットマップディメンションを読み取ります。
画像をメモリにロードする前にビットマップの寸法を読み取ることで、
メモリエラー?学びましょう
inJustBounds = trueを使用
ここに、メモリにロードする前に画像の次元を取得するためのテクニックがあります。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
上記のコードスニペットでは、画像やビットマップは提供されません。ビットマップオブジェクトの場合はnullを返します。しかし、それは間違いなくその画像の幅と高さを返します。これはR.id.myimageです。
これで、画像の幅と高さが決まりました。次の要因に基づいて画像を拡大または縮小できます。
デバイスの画面サイズと密度。
ビットマップ構成は、画像の色空間/色深度です。 Androidのデフォルトのビットマップ構成はRGB_8888で、ピクセルあたり4バイトです。
ピクセルあたり2バイトを使用するRGB_565カラーチャネルを使用する場合。同じ解像度のメモリ割り当ての半分:)
リサイクルの目的でinBitmapプロパティを使用します。
静的なDrawable Objectはガベージコレクションできないため作成しないでください。
マニフェストファイルで大きなヒープを要求します。
多くの画像処理(メモリを大量に消費するタスク)を実行している場合は複数のプロセスを使用するか、NDK(c、c ++を使用したネイティブ開発)を使用する
これは、ビットマップを直接ロードしているために発生し、多くのメモリを消費します。代わりに、_profileBitmapの画像の縮小版を使用してください。この男はそれをかなりよく説明しています。 http://androidcocktail.blogspot.in/2012/05/solving-bitmap-size-exceeds-vm-budget.html
使い終わったら、ビットマップでrecycle()を呼び出してみてください。これにより、すべての画像データが消去され、メモリが解放されます。この後でビットマップを描画しようとすると、アプリがクラッシュします。クラッシュが発生した場合は、ビットマップ上にまだ何が残っているかを見つけるのに役立つことがあります。
ベクトルDrawableを使用できます。 xmlファイルを使用して画像を記述するため、消費メモリが少なくなります。そのためには、画像にSVG形式を使用し、次の2つのソリューションのいずれかを使用してxmlファイルを生成する必要があります。
詳細については、このリンクを確認してください。
https://developer.Android.com/studio/write/vector-asset-studio.html
この問題が発生したのは、ビットマップを1回変更してから、変更されたバージョンをもう一度変更したため、同じビットマップの3つのバージョン(元のバージョンと2つの変更されたバージョン)が同時にメモリに存在するためです。
画像編集コードを変更して両方の変更を同じビットマップに一種のバッチプロセスとして適用し、アプリがメモリに保持する必要のある変更されたバージョンの数を半分にして修正しました。
大きな画像では、それらを小さなサイズにサンプリングすることで回避できます。以下の例を使用-
File f = new File(selectedImagePath);
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, 720, 1280); //My device pixel resolution
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap bmpPic = BitmapFactory.decodeStream(new FileInputStream(f), null, options);
Bitmap bmpPic1 = Bitmap.createBitmap(bmpPic, 0, 0, bmpPic.getWidth(), bmpPic.getHeight(), mat, true);
img.setImageBitmap(bmpPic1); //img is your ImageView
リファレンス- http://developer.Android.com/training/displaying-bitmaps/load-bitmap.html
電話の電源をオフにしてから再度オンにしたときにも同じ問題が発生しました。ビットマップをnullに設定してSystem.gc()を呼び出すだけです。すべての問題を修正しました。