2011-03-01 70 views
2

我有一个活动有时会突然终止,但没有任何异常被报告或记录。该活动只是突然结束,应用程序返回到堆栈中的前一个活动。 我使用ACRA(http://code.google.com/p/acra/)来捕获和报告错误,并且它适用于应用程序中的所有其他错误,但在这种情况下,它不会检测到任何已抛出的异常。在Logcat中也没有任何报道。活动终止突然没有任何异常

它总是发生在应用程序中相同的“地点”,当用户采取某个动作时,但它非常间歇,我还没有在与调试器连接时发生。 除了ACRA和Logcat之外,还有其他选项可用于确定活动发生的情况吗?或者这是Android活动的世界中的“已知?”

如果很重要,这个活动正在做位图操作和保存;我必须采取措施避免潜在的内存不足错误;但是当ACRA发生OOM异常时,我得到了这些异常,因此我认为这不是OOME引起的。

在似乎失败的地方,Activity创建一个AsyncTask并执行它。下面是对的AsyncTask代码(ActivityAsyncTask是一个非常简单的超类; EditPhotoEctivity是垂死没有例外的一个,有时在这个任务的创建或执行):

import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.IOException; 

import org.apache.commons.io.FileUtils; 

import android.graphics.Bitmap; 
import android.graphics.Bitmap.CompressFormat; 
import android.media.MediaScannerConnection; 
import android.media.MediaScannerConnection.MediaScannerConnectionClient; 
import android.net.Uri; 
import android.view.View; 

public class CompositeAndSavePictureTask extends ActivityAsyncTask<File, Void, Uri> 
    implements MediaScannerConnectionClient { 

    public static final String FILE_EXTENSION = ".jpg"; 
    private static final int COMPRESSION_QUALITY = 100; 

    private File file; 
    private Uri mSavedImageUri; 
    private MediaScannerConnection mMediaScannerConnection; 


    public CompositeAndSavePictureTask(EditPhotoActivity owningActivity) { 
     super(owningActivity); 
     mMediaScannerConnection = new MediaScannerConnection(owningActivity, this); 
    } 


    @Override 
    protected EditPhotoActivity getOwner() { 
     return (EditPhotoActivity) super.getOwner(); 
    } 


    @Override 
    protected void onPreExecute() { 
     getOwner().toggleControlsVisibility(false); 
    } 

    @Override 
    protected Uri doInBackground(File... params) { 
     file = params[0]; 
     Bitmap picture = null; 
     View mainContentView = getMainContentView(); 

     try { 
      picture = captureBitmap(mainContentView); 
      saveBitmap(picture); 
     } catch (Exception ex) { 
      LogUtils.logError(this, "Could not save photo", ex); 
      setError(ex); 
      return null; 
     } finally { 
      cleanUpCapture(mainContentView, picture); 
     } 

     try { 
      mMediaScannerConnection.connect(); 
      synchronized (mMediaScannerConnection) { 
       mMediaScannerConnection.wait(); 
      } 
     } catch (InterruptedException ex) { 
      LogUtils.logInfo(this, "MediaScannerConnection was interrupted during scan."); 
      setError(ex); 
     } 

     return mSavedImageUri; 
    } 


    protected Bitmap captureBitmap(View mainContentView) throws Exception { 
     mainContentView.setDrawingCacheEnabled(true); 
     return mainContentView.getDrawingCache(); 
    } 


    protected void cleanUpCapture(View mainContentView, Bitmap capturedBitmap) { 
     mainContentView.setDrawingCacheEnabled(false); 

     if (capturedBitmap != null) { 
      capturedBitmap.recycle(); 
     } 
    } 


    protected void saveBitmap(Bitmap bitmap) throws IOException { 
     BufferedOutputStream outStream = null; 
     try { 
      outStream = new BufferedOutputStream(FileUtils.openOutputStream(file)); 
      bitmap.compress(CompressFormat.JPEG, COMPRESSION_QUALITY, outStream); 
     } finally { 
      try { 
       if (outStream != null) { 
        outStream.close(); 
       } 
      } catch (IOException ex) { 
       LogUtils.logError(this, "Could not close output stream", ex); 
      } 
     } 
    } 


    @Override 
    protected void onPostExecute(Uri savedFileURI) { 
     getOwner().toggleControlsVisibility(true); 
     getOwner().onSaveResult(savedFileURI); 
    } 


    public void onMediaScannerConnected() { 
     mMediaScannerConnection.scanFile(file.getPath(), null /* mimeType */); 
    } 


    public void onScanCompleted(String path, Uri uri) { 
     mMediaScannerConnection.disconnect(); 
     mSavedImageUri = uri; 
     synchronized (mMediaScannerConnection) { 
      mMediaScannerConnection.notify(); 
     } 
    } 

} 

又见view.getDrawingCache() only works once,其中有有些关系,但情况稍有不同。

欢迎任何想法。

+0

您能否提供一些源代码?现在它会像蒙着眼睛的射击一样。 – Shade 2011-03-01 14:58:38

+1

你能否在某处“完成”你的活动? – 2011-03-01 15:18:03

+2

@nicholas我已经仔细检查和三重检查任何无意中调用完成()。活动中唯一的是成功完成或其他预期条件。 – 2011-03-01 15:38:34

回答

0

请原谅新手评论,但如果它没有异常终止,你可能会在某个地方捕捉它,程序继续快乐的方式,但处于无效状态。

+0

@ r-hughes我希望这很简单,该代码已被双重和三重检查的那种事情。 我添加了一些日志记录,似乎失败发生在行 'mainContentView.setDrawingCacheEnabled(true);' 'return mainContentView.getDrawingCache();' – 2011-03-24 13:14:20

+0

是的,你已经记录了日志。如果由于内存不足或其他原因导致Android终止它,您的onPause会被调用。 hm ... 如果.getDrawingCache()返回null,那么对您的Activity有什么影响? – 2011-03-24 20:27:45

+0

我将它缩小为'mainContentView.getDrawingCache();'导致突然终止,但在那个时候不得不转移到其他项目。希望我能找到一种方法可靠地重现这一点,以便我可以做更多的调试。 – 2011-04-06 19:21:11

1

我以前有类似的问题。我试图打开一个文件进行阅读,但没有输入“/sdcard/something.txt”的完整地址,而是在没有SD卡部分的情况下给出了错误的路径(只是“something.txt”)。在经历了很多痛苦之后,我发现如果你想让程序打开一些并不真正存在的东西,那么这个活动只会在没有任何通知的情况下结束(对于控制台,logcat等)。由于它不会发回错误,它不会在“catch”分支上。

所以,我会建议检查文件操作。

声明:我知道当使用ndk和本机代码尝试打开错误的路径时,会导致这种行为,但是如果您在java代码中犯这个错误,我想它会是一样的。