いくつかの写真を撮り、サイズを変更してバックエンドサーバーに送信するAndroidアプリがあります。このアプリは、Samsung Galaxy S3を除く他のすべての電話(ジンジャーブレッドとアイスクリームサンドイッチ)で完全に正常に動作します。写真を撮ってサイズを変更しようとすると、メモリが不足します。最初はサイズ変更の問題だと思い、insamplesizeでビットマップオブジェクトを実装してすべてを試しましたが、それでもクラッシュし続けました。その後、アプリを最初に起動したときに、大量のメモリを消費していることに気付きました。HTCや他のすべての電話では、アプリを起動すると約4 MBを消費しますが、GalaxyS3では約30MGを消費します。これは約10倍です。何が原因でそれだけ多くのメモリを消費するのか理解できないようです。私はすべてのオブジェクトとレイアウトを適切にリサイクルしています(私は思います)。
public static void resizeImage(String pathOfInputImage,
String pathOfOutputImage) {
try {
int inWidth = 0;
int inHeight = 0;
float factor;
InputStream in = new FileInputStream(pathOfInputImage);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
inWidth = options.outWidth;
inHeight = options.outHeight;
in.close();
in = null;
options = null;
if (inWidth > inHeight) {
factor = (float) inHeight / 480;
} else {
factor = (float) inWidth / 480;
}
options = new BitmapFactory.Options();
Bitmap roughBitmap;
if(Build.VERSION.SDK_INT < 12) {
System.gc();
}
try
{
in = new FileInputStream(pathOfInputImage);
options.inSampleSize = 4;
roughBitmap = BitmapFactory.decodeStream(in, null, options);
}
catch (OutOfMemoryError e)
{
roughBitmap = Utils.fetchRoughBitmap(pathOfInputImage, factor);
}
finally
{
roughBitmap = Utils.fetchRoughBitmap(pathOfInputImage, factor);
}
in.close();
in = null;
boolean rotate = false;
Bitmap rotatedBitmap = null;
if (isNeedToRotate(pathOfInputImage)) {
rotate = true;
Matrix m = new Matrix();
m.postRotate(90);
try
{
rotatedBitmap = Bitmap.createBitmap(roughBitmap, 0, 0,
roughBitmap.getWidth(), roughBitmap.getHeight(), m,
true);
}
catch (OutOfMemoryError e)
{
rotatedBitmap = Bitmap.createBitmap(roughBitmap, 0, 0,
roughBitmap.getWidth()/2, roughBitmap.getHeight()/2, m,
true);
}
}
if (rotate) {
Utils.log(TAG, "Rotate Invoked :------->");
int temp = inHeight;
inHeight = inWidth;
inWidth = temp;
}
options.inSampleSize = Math.round(factor);
float dstWidth = (int) inWidth / factor;
float dstHeight = (int) inHeight / factor;
Bitmap resizedBitmap;
if (rotate) {
try
{
resizedBitmap = Bitmap.createScaledBitmap(rotatedBitmap,
(int) dstWidth, (int) dstHeight, true);
}
catch (OutOfMemoryError e)
{
resizedBitmap = Bitmap.createScaledBitmap(rotatedBitmap,
(int) dstWidth/2, (int) dstHeight/2, true);
}
} else {
try
{
resizedBitmap = Bitmap.createScaledBitmap(roughBitmap,
(int) dstWidth, (int) dstHeight, true);
}
catch (OutOfMemoryError e)
{
resizedBitmap = Bitmap.createScaledBitmap(roughBitmap,
(int) dstWidth/2, (int) dstHeight/2, true);
}
}
try
{
FileOutputStream out = new FileOutputStream(pathOfOutputImage);
resizedBitmap.compress(Bitmap.CompressFormat.PNG, 80, out);
}
catch (Exception e) {
Utils.log("Image", e.getMessage() + e);
}
//Free up the memory.
roughBitmap.recycle();
resizedBitmap.recycle();
if (rotatedBitmap != null) {
rotatedBitmap.recycle();
}
} catch (IOException e) {
Utils.log("Image", e.getMessage() + e);
}
}
private static Bitmap fetchRoughBitmap(String pathOfInputImage, float factor)
{
Bitmap roughBitmap = null;
try
{
FileInputStream in = new FileInputStream(pathOfInputImage);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = Math.round(factor);
roughBitmap = BitmapFactory.decodeStream(in, null, options);
return roughBitmap;
}
catch (OutOfMemoryError mem_error)
{
return Utils.fetchRoughBitmap(pathOfInputImage, factor+1);
}
catch (FileNotFoundException e)
{
//return Utils.fetchRoughBitmap(pathOfInputImage, factor+1);
return roughBitmap;
}
}
このコードは、メモリが不足しなくなるまで再帰ループを実行するため、正常に機能しますが、結果の画像は約300x300ピクセルであり、少なくとも640x480である必要があります。私の質問は次のとおりです。
- Galaxy S3がHTC電話で60%ではなく、アプリを最初にロードしたときに最大90%のメモリを使用する理由を誰かに教えてもらえますか?
- アプリのメモリが不足する原因となっているサイズ変更コードで何か問題がありますか?
私はすでにこの問題に3日間費やしているので、どんな助けでも大歓迎です:-(。