1

In order to debug a user problem I can't reproduce, I am trying to put a button into my app that gathers up logcat output and emails it. I am having trouble.

First, I tried to use acra. I dropped down one rathole for awhile. I got

java.lang.RuntimeException: com.android.build.api.transform.TransformException: Error while generating the main dex list.
at ...
Caused by: com.android.tools.r8.errors.CompilationError: Program type already present: android.support.v4.widget.EdgeEffectCompat

and read about trying to resolve clashing classes from different libraries (e.g., this, but there were more I can't find).

I decided to try a simpler way, outlined here: a single function to grab the logs with logcat and email. One wrinkle is that newer versions of android don't let you grab that file directly, you have to use a FileProvider.

I ended up with this:

/**
 * Save logcat in a file and return an Intent that emails it.
 *
 * @return  intent to email log file
 */
private static Intent sendLogcatMail() {
    // save logcat in file
    File outputFile = new File(Environment.getExternalStorageDirectory(),
            "logcat.txt");
    try {
        // last 2000 lines of the log, in 'time' format
        Runtime.getRuntime().exec(
                "logcat -v time -t 2000 -f " + outputFile.getAbsolutePath());
    } catch (IOException e) {
        Log.e(LOGGER_TAG, "Error in logcat:" + Tools.getStackTrace(e));
    }

    Log.i(LOGGER_TAG, "logcat size: " + outputFile.length());
    //send file using email
    Intent emailIntent = new Intent(Intent.ACTION_SEND);
    emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    // Set type to "email"
    emailIntent.setType("vnd.android.cursor.dir/email");
    String to[] = {SEND_LOGS_EMAIL};
    emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
    // FileProvider
    // See https://developer.android.com/reference/android/support/v4/content/FileProvider
    // See https://stackoverflow.com/a/38858040/34935
    // See https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en
    Uri logUri = FileProvider.getUriForFile(Tools.getContext(),
            BuildConfig.APPLICATION_ID + ".provider",
            outputFile);
    // the attachment
    emailIntent.putExtra(Intent.EXTRA_STREAM, logUri);
    // the mail subject
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "App logs");
    return Intent.createChooser(emailIntent , "Send email...");
}

Now when I run in the simulator, that debug line shows the logcat file is always of size zero, even though I see the logcat in Android Studio. I tried emphasizing that my app was debuggable with this in my build.gradle:

   release {
        // ...
        // make sure logcat gets debug output
        debuggable true
    }

That did nothing.

How can I gather up debug logs to email them, or otherwise get them from a remote app to where I can see them? I am utterly confused.

dfrankow
  • 20,191
  • 41
  • 152
  • 214
  • I suggest to use firebase crash reporting it's really make the life easier – Abdulmalek Dery Jul 08 '18 at 21:11
  • 1
    Thanks for the suggestion. First, it's already been deprecated for Crashalytics: https://firebase.googleblog.com/2018/03/firebase-crashlytics-graduates-from-beta.html. Second, I don't have a crash. The app just isn't functioning correctly (not uploading things when it's on wifi). – dfrankow Jul 08 '18 at 21:41

1 Answers1

0

Runtime#exec does not wait for the process to be completed (or even to be started, perhaps). So you need to invoke waitFor() on the result in order to await logcat termination:

int exitStatus = Runtime.getRuntime()
        .exec("logcat -v time -t 2000 -f " + outputFile.getAbsolutePath())
        .waitFor();
if (exitStatus != 0) {
    // Something went wrong running logcat, handle error. Output file might not exist.
}
Thomas
  • 174,939
  • 50
  • 355
  • 478