我有一个Android应用程序,可以拍摄一些照片,调整它们的大小并将它们发送到后端服务器。这个应用在所有其他手机上都可以正常工作(Gingerbread 和 Ice cream sandwich),但在三星Galaxy S3上却出现了问题。每当它尝试拍摄照片并调整大小时,就会耗尽内存。起初我认为这是调整大小部分的问题,我使用insamplesize实现了bitmap对象并尝试了各种方法,但仍然一直崩溃。然后我意识到当应用程序首次启动时,它会使用大量内存。在HTC和所有其他手机上,当我的应用程序启动时,它会使用约4 MB的内存,但在Galaxy S3上,它会使用约30 MG,几乎是其他手机的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在首次加载我的应用时会使用高达90%的内存,而HTC手机只使用60%吗?
- 我的重新调整大小代码是否有任何错误导致我的应用程序耗尽内存?
非常感谢任何帮助,因为我已经花了3天时间来解决这个问题 :-(。
System
中有一个方法可以返回程序分配的字节数,但我不确定安卓是否支持它。而且它也不是很具体,只能作为代码中触发大量分配的部分的大致测量。不过我认为在这种情况下这就足够了。 - Wug