2011-03-01 4 views
2

때때로 예외가보고되거나 기록되지 않고 갑자기 종료되는 활동이 있습니다. 활동이 갑자기 종료되고 앱이 스택의 이전 활동으로 돌아갑니다. ACRA (http://code.google.com/p/acra/)를 사용하여 오류를 캡처하고보고하며 앱의 다른 모든 오류에도 잘 작동하지만이 경우에는 예외가 발생하지 않았 음을 감지하지 못합니다. Logcat에보고 된 것도 없습니다.아무런 예외없이 갑작스럽게 종료되는 활동

사용자가 특정 조치를 취할 때 항상 앱의 동일한 "장소"에서 발생하지만 간헐적이며 아직 디버거와 연결되어있는 동안 문제가 발생하지 않았습니다. 활동에 어떤 일이 일어나고 있는지 결정하기위한 다른 옵션 (ACRA 및 Logcat 제외)이 있습니까? 아니면 안드로이드 활동 세계에서 "알려진"것입니까?

중요한 점이 있다면,이 액티비티는 비트 맵 조작 및 저장을 수행하고 있습니다. 나는 메모리 오류 가능성을 피하기 위해 조치를 취해야했다. OOM 예외가 발생했을 때 ACRA보고를 받고 있었으므로 이것이 OOME 때문일 것으로 생각하지 않습니다.

활동이 실패한 시점에서 활동은 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

+1

어딘가에 활동을 마치시겠습니까? –

+2

@nicholas finish()에 대한 부주의 한 호출을 두 번 확인하고 세 번 검사했습니다. 활동의 유일한 요소는 성공적인 완료 또는 기타 예상 조건입니다. –

답변

0

초보자 용 코멘트를 용서해주십시오. 예외없이 종료하는 경우, 어딘가에 잡는 중일 수 있으며 프로그램이 즐거운 방법으로 계속되지만 유효하지 않은 상태입니다.

+0

@ r-hughes 나는 그게 간단했다. 그런 종류의 일에 대해 코드가 두 배 및 세 번 검사되었습니다. 일부 로깅을 추가했는데 오류가 라인 어딘가에서 발생하는 것 같습니다. 'mainContentView.setDrawingCacheEnabled (true); 'return mainContentView.getDrawingCache(); ' –

+0

그래, 로깅이 처리되었습니다. 안드로이드가 메모리 부족이나 다른 이유 때문에 종료 된 경우 onPause가 호출됩니다. hm ... .getDrawingCache()가 null을 반환하면 활동에 어떤 영향을 미칩니 까? –

+0

'mainContentView.getDrawingCache();'로 축소했습니다. 갑작스런 해고를 초래했지만 그 시점에서 다른 프로젝트로 이동해야했다. 디버깅을 좀 더 할 수 있기를 바란다. –

1

이전에 비슷한 문제가있었습니다. 독서를 위해 파일을 열려고했지만 "/sdcard/something.txt"라는 완전한 주소를 입력하는 대신 sdcard 부분이없는 잘못된 경로 ("something.txt") 만 입력했습니다. 많은 고통을 겪은 후에 나는 프로그램이 실제로 존재하지 않는 무언가를 열길 원한다는 것을 발견했다. 활동은 어떤 경고 (콘솔, 로그 캣 등)에 대해서도 끝내 버린다. 오류를 다시 보내지 않으므로 "catch"브랜치로 이동하지 않습니다.

따라서 파일 검사를 제안 할 것입니다.

면책 조항 : ndk 및 원시 코드를 사용하여 잘못된 경로를 열려고 시도 할 때 이러한 종류의 동작이 발생하지만 Java 코드에서이 실수를 한 경우 동일하다고 가정합니다.

관련 문제