2011-03-01 27 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代碼中犯這個錯誤,我想它會是一樣的。

相關問題