2

I have an Activity that sometimes terminates abruptly but without any exception being reported or logged. The Activity just ends suddenly and the app returns to the previous Activity in the stack. I'm using ACRA (http://code.google.com/p/acra/) to capture and report errors, and it works well for all other errors in the app, but in this one case it does not detect any exception having been thrown. Nor is anything reported in Logcat.

It always happens at the same "place" in the app, when the user takes a certain action, but it is very intermittent and I've yet to make it happen while attached with the debugger. Are there any other options (besides ACRA and Logcat) for determining what is happening to the Activity? Or is this something in the world of Android Activities that is "known?"

If it matters, this Activity is doing Bitmap manipulation and saving; I've had to take steps to avoid potential out of memory errors; but I was getting ACRA reports of OOM exceptions when they did occur, so I don't think this is due to OOME.

At the point where it seems to fail, the Activity creates an AsyncTask and executes it. Here's the code for the AsyncTask (ActivityAsyncTask is a really simple super class; EditPhotoEctivity is the one that is dying without an exception, sometime during the creation or execution of this task):

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();
        }
    }

}

See also view.getDrawingCache() only works once, which has some relation but is a slightly different scenario.

Any and all ideas are welcomed.

Community
  • 1
  • 1
E-Riz
  • 31,431
  • 9
  • 97
  • 134
  • Could you please provide some source code? Right now it will be like shooting blindfolded. – Shade Mar 01 '11 at 14:58
  • 1
    Could you be 'finishing' your Activity somewhere? – nicholas.hauschild Mar 01 '11 at 15:18
  • 2
    @nicholas I've double-checked and triple-checked for any inadvertent calls to finish(). The only ones in the Activity are for successful completion or other expected conditions. – E-Riz Mar 01 '11 at 15:38
  • 2
    @Shade I just edited the question with some code. – E-Riz Mar 01 '11 at 15:48
  • Perhaps one of those "expected conditions" is happening unexpectedly? That would explain the lack of an error. – Amplify91 Mar 01 '11 at 16:00
  • 2
    @Amplify91 There are 4 calls to finish(), all but one of them are during the initialization of the Activity. The one that happens as the result of user interaction comes after the AsyncTask would have completed and saved its file. I've verified that when the abrupt failure happens, the file has not been saved and the code never reached that call to finish(). – E-Riz Mar 01 '11 at 16:14
  • How did you solve this problem? – Talha Nov 14 '16 at 05:32
  • @Talha, I never did solve it. I eventually moved on to other projects. – E-Riz Nov 14 '16 at 12:46
  • Ok, I had similar issue that app was closing without any exception, during `asyncTask` process, no `logcat` trace whatsoever, on clearing all filters it said `DeadObjectException`, and some `amazon package` exception (I had nothing to do with amazon services), it was on `Moto X`, tested same app on `Galaxy S6`, worked perfect. To this day I dont know why it was happening, and it still crashes on `Moto X` while works perfect on other devices. – Talha Nov 14 '16 at 13:02

2 Answers2

1

I had a similar problem before. I was trying to open a file for reading, but instead of typing the complete address which was "/sdcard/something.txt", I gave it the wrong path (just "something.txt") without the sdcard part. After a lot of pain I have discovered that if you want the program to open something that is not really there, the activity just ends whitout any notice (to to console, to logcat etc. ). As it won't send back an error, it won't go on the "catch" branch.

So, I would suggest checking the file opperations.

Disclaimer: I know for sure that this causes this kind of behavior when trying to open the wrong path using the ndk and native code, but I suppose it would be the same if you do this mistake from in java code.

Mona Paun
  • 386
  • 3
  • 8
0

Please forgive the newbie comment, but if it's terminating without a Exception, you may be catching it somewhere and the program is continuing on it's merry way, but in an invalid state.

R Hughes
  • 640
  • 9
  • 22
  • @r-hughes I wish it were that simple; the code has been double- and triple- checked for that kind of thing. I added some logging and it seems that the failure is happening somewhere in the lines `mainContentView.setDrawingCacheEnabled(true);` `return mainContentView.getDrawingCache();` – E-Riz Mar 24 '11 at 13:14
  • Yeah, you've got the logging covered. If Android terminated it due to low memory or some other obsure reason, your onPause would get called for that. hm... If .getDrawingCache() returned a null, what effect would that have on your Activity? – R Hughes Mar 24 '11 at 20:27
  • I reduced it to 'mainContentView.getDrawingCache();' causing the abrupt termination, but at that point had to move on to other projects. Wish I could have found a way to reliably reproduce this so I could do some more debugging. – E-Riz Apr 06 '11 at 19:21