【发布时间】:2015-11-06 02:49:43
【问题描述】:
我有一个活动有时会突然终止,但没有报告或记录任何异常。 Activity 突然结束,应用程序返回堆栈中的前一个 Activity。 我正在使用 ACRA (http://code.google.com/p/acra/) 来捕获和报告错误,它适用于应用程序中的所有其他错误,但在这种情况下,它没有检测到任何已引发的异常。 Logcat 中也没有报告任何内容。
当用户执行某个操作时,它总是发生在应用程序中的同一个“位置”,但它是非常间歇性的,我还没有在附加调试器时实现它。 是否有任何其他选项(除了 ACRA 和 Logcat)来确定活动发生了什么?或者这是 Android 活动世界中“已知”的东西?
如果重要的话,这个 Activity 正在做 Bitmap 操作和保存;我不得不采取措施避免潜在的内存不足错误;但是当 OOM 异常发生时,我收到了 ACRA 报告,所以我认为这不是 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,它有一些关系,但情况略有不同。
欢迎任何和所有想法。
【问题讨论】:
-
能否提供一些源代码?现在就像蒙着眼睛拍摄一样。
-
你能在某个地方“完成”你的活动吗?
-
@nicholas 我已经仔细检查和三重检查是否有任何无意调用完成()。活动中的唯一条件是成功完成或其他预期条件。
-
@Shade 我刚刚用一些代码编辑了这个问题。
-
@Amplify91 有 4 次对 finish() 的调用,除 1 次外,其余都是在 Activity 初始化期间。由于用户交互而发生的情况发生在 AsyncTask 完成并保存其文件之后。我已经验证,当突然失败发生时,文件还没有保存,代码也没有到达对 finish() 的调用。