1

I have option to save Bitmap to sdcard in my app.
I am doing saving in AsyncTask method. here is what i do on background

public File saveImageToExternalStorage(Bitmap image, String name) {
 String fullPath = Environment.getExternalStorageDirectory().getAbsolutePath() + APP_PATH_SD_CARD + APP_THUMBNAIL_PATH_SD_CARD;

 try {
 File dir = new File(fullPath);
 if (!dir.exists()) {
 dir.mkdirs();
 }
 OutputStream fOut = null;
 File file = new File(fullPath, name.replaceAll("/", "").trim());
 file.createNewFile();
 fOut = new FileOutputStream(file);
 image.compress(Bitmap.CompressFormat.JPEG, 50, fOut);
 fOut.flush();
 fOut.close();
 MediaStore.Images.Media.insertImage(getApplicationContext().getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());

 return file;

 } catch (Exception e) {
 return null;
 }

I am displaying some information about failing to save and etc for user if I get null from this method. I though this should be sufficient, yet I got reported OutOfMemory crash by one user from this method. Stacktrace:

java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:527)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:301)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:326)
at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:796)
at com.stancedcars.wallpapers.FullSelected.saveImageToExternalStorage(FullSelected.java:223)

I would love to solve OutOfMemory issue, but Bitmaps are heavy in size, high resolution images, I wouldn't want to reduce quality. More importantly I would like to know why the app crashed even though it was in try catch ?

4

3 回答 3

6

您捕获了通用异常,而 OutOfMemoryError 是一个错误,它也是 Throwable。

你有什么

java.lang.Object
   ↳    java.lang.Throwable
       ↳    java.lang.Error
           ↳    java.lang.VirtualMachineError
               ↳    java.lang.OutOfMemoryError

你能抓住什么

java.lang.Object
   ↳    java.lang.Throwable
       ↳    java.lang.Exception

因此,要捕获所有可能的 Throwable,您需要捕获

try {
     //...
} catch (Throwable e) {
    e.printStackTrace();
}
于 2013-04-24T06:28:44.953 回答
1

使用 catch OutOfMemoryError 不是异常!

try {
    // your code
} catch (OutOfMemoryError e) {
}
于 2013-04-24T06:30:43.663 回答
0

一旦程序内存不足,就很难恢复。您需要仔细考虑如何在发生这种情况时尝试清理。例如,在您的 saveImageToExternalStorage 中,如果 try/catch 内部发生异常,它不会清理 fOut。所以你应该做一些事情,比如 put

OutputStream fOut = null;

在 try/catch 之外,然后在 try/catch 的 finally 块中将其关闭。并注意 finally 块的 catch 中进一步异常的可能性。

于 2013-04-24T06:30:29.210 回答