How to create Application Error in Production (Client)

5

I'm looking for a way (efficient and practical) to globally capture all Exceptions not handled by the application (the ones that take the application to crash or "The application stopped working!") p>

Questions:

  • Is there any method void main() , as in Java I can capture these exceptions in a centralized way, before the application crash ?
  • Is there any feature available in the Android API for these purposes?
  • What would be the most efficient and practical way to create this feature?

I would like an implementation solution, I would not like to use third-party libraries. For I believe that my final implementation would be something very singular and specific. = D

  

Complementary information : What should be possible to do in the global Exceptions grabber (You do not need to implement these cases in the response (only necessary information to continue the implementation)): / p>      

  • Capture the exception stack;
  •   
  • Be able to instantiate and use the java.io package; (for saving logs to a file)
  •   
  • (Optional) Access the Context of the application, in order to instantiate a connection to SQLite; (for recording logs in database)
  •   
  

Note: I do not want to try to recover the application, but only to have this information in order to analyze it and improve the efficiency of the application.

     

Detail: I have already seen and did not help me in my doubt.

    
asked by anonymous 23.04.2015 / 17:00

2 answers

6

Just as Paulo Rodrigues quoted, Android, more specifically the JVM, allows you to register a Handler to Exception's untreated.

And, I believe, any library that allows error reporting uses the same technique.

Treating uncaught Exception's

The simplest and perhaps most organized way to do this is by using the Application class. Where at the beginning of the application, in the onCreate method, you register Handler .

An example I use a lot:

public class Application extends android.app.Application implements Thread.UncaughtExceptionHandler {

    private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;

    @Override
    public void onCreate() {
        super.onCreate();
        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        // Aqui você pode tratar a Exception...
        mDefaultExceptionHandler.uncaughtException(thread, ex);
    }
}

Okay, with just that, it does not answer every question. Thread.UncaughtExceptionHandler answers only your first question.

With Thread.UncaughtExceptionHandler I think it's possible to answer the last two, but you need a little more code.

Writing to file

For the second question, I'm sure it's possible, because some of the treatments I do in some app's are to write to a file the error log, but I usually use a Thread to do this. >

A simple way:

@Override
public void uncaughtException(Thread thread, final Throwable ex) {
    new Thread(){
        @Override
        public void run() {
            File file = new File("NOME_DO_ARQUIVO");
            FileWriter writer = null;

            try {
                writer = new FileWriter(file);
                writer.write(throwableToString(ex));
            } catch (IOException e) {
            } finally {
                close(writer);
            }
        }
    }.start();
}

private String throwableToString(Throwable t) {
    StringWriter stringWriter = new StringWriter();
    PrintWriter printWriter = new PrintWriter(stringWriter, false);

    t.printStackTrace(printWriter);

    printWriter.flush();
    stringWriter.flush();

    return stringWriter.toString();
}

Saving Exception in SQLite

Yes, it is possible. I never did this, but in line with this project / a> is possible.

A leaner example would be:

@Override
public void uncaughtException(Thread thread, final Throwable ex) {
    new Thread(){
        @Override
        public void run() {
            SQLiteDatabase db = new SeuSQLiteOpenHelper(Application.this).getWritableDatabase();

            String sql = "insert into exceptions(exception, created_at) values (?, ?)";

            Object args[] = {
                    throwableToString(ex),
                    System.currentTimeMillis() / 1000
            };

            try { 
                db.execSQL(sql, args);
            } catch(Exception e){
            } finally {
                db.close();
            }
        }
    }.start();
}

And as alerted by Fernando, the declaration of class Application in AndroidManifest was missing:

<application
    <!-- Demais atributos -->
    android:name=".application.Application" />
    
23.04.2015 / 19:44
0

High maintenance!

Such an implementation generates other work points and more maintenance, for example!
1 - Create a way to send this log. 2 - Control the repetition of sending the same error. (N users)
3 - Support connection load and traffic for this log.
4 - Minimize the negative image of a CRASH in your application
5 - Ensure that logging is done even if a CRASH occurs.
6 - Inform and ask the user to authorize the error log
and also additional information for the same.
7 - Implement an application to receive these logs.

Something more professional and worked thinking about these problems would be!

ACRA is a library that allows The Android Application to automatically post your crash reports to a Google Doc form (deprecated). It is targeted to Android application developers to help them get data from their applications when they stop working or misbehave.

More information: link                    link

    
24.04.2015 / 18:58