Android Tutorial Uncaught Exceptions

By default, when there is an uncaught exception the program will show a message box with the error title and the user will be asked whether they want to continue or not.

There are several problems with this behavior:
1. The user cannot really know whether the program can continue correctly after the uncaught exception.
2. A crash report will not be sent to Google Play as the error was eventually caught internally.
3. It is inconsistent as the dialog only appears when the error happens with an activity context.
4. It was not possible to override this behavior and allow sending the error with an email for example.

Starting from B4A v5.50 it is possible to change this behavior.
If there is a sub named Application_Error in the Starter service module then the default error dialog will never appear.
Note that the starter service template includes this sub. It is recommended to include this sub in all projects.

B4X:
'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
   Return True
End Sub

If you return True from this sub then the OS default exceptions handler is called. The result is that the app will crash and the crash report will be sent to Google Play (if the user allows it).
This is a good and standard behavior.

If you return False then the default exceptions handler will not be called. This means that the app will continue to run.

A proper usage of this is to allow you to use alternative methods to send the crash report. For example you can use HttpUtils2 to send the StackTrace to your server and then kill the process in the JobDone event.

Notes

- Application_Error will only be called in Release mode. In Debug mode the program will print the error message in the logs and will end.
- Errors that happen when the app is started, before the Starter service is ready will not be trapped. The OS default exceptions handler will handle those errors.
- The starter service must be running for this sub to be raised. It will be running unless you explicitly stop it.

An example of catching the recent logs and sending them with an intent is attached.

 

Attachments

  • SendEmailWithCrashLogs.zip
    7.8 KB · Views: 1,878
Last edited:

ArminKH

Well-Known Member
By default, when there is an uncaught exception the program will show a message box with the error title and the user will be asked whether they want to continue or not.

There are several problems with this behavior:
1. The user cannot really know whether the program can continue correctly after the uncaught exception.
2. A crash report will not be sent to Google Play as the error was eventually caught internally.
3. It is inconsistent as the dialog only appears when the error happens with an activity context.
4. It was not possible to override this behavior and allow sending the error with an email for example.

Starting from B4A v5.50 (which was not yet released) it is possible to change this behavior.
If there is a sub named Application_Error in the Starter service module then the default error dialog will never appear.
Note that the starter service template includes this sub. It is recommended to include this sub in all projects.

B4X:
'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
   Return True
End Sub

If you return True from this sub then the OS default exceptions handler is called. The result is that the app will crash and the crash report will be sent to Google Play (if the user allows it).
This is a good and standard behavior.

If you return False then the default exceptions handler will not be called. This means that the app will continue to run.

A proper usage of this is to allow you to use alternative methods to send the crash report. For example you can use HttpUtils2 to send the StackTrace to your server and then kill the process in the JobDone event.

Notes

- Application_Error will only be called in Release mode. In Debug mode the program will print the error message in the logs and will end.
- Errors that happen when the app is started, before the Starter service is ready will not be trapped. The OS default exceptions handler will handle those errors.
Is this possible to use this sub directly in activity?i know maybe by callsub but maybe some apps don't need any starter service
 

ArminKH

Well-Known Member
Ok and also can u please add an extra variable for LineNumber separatly? Because i want to use this future insted try catch and i want to know which line is sent error message to that sub
I know maybe line number can be accessable inside exception message but i want an extra and separate variable for that if is possible
No. It must be inside the Starter Service. There is no reason not to use the starter service.
Yes but when my app has not any global resources or initializes starter service is necesaary?
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
The line number is not known in release mode. Only the java line number (which is included in the stack trace).

Yes but when my app has not any global resources or initializes then starter service is necesaary?
It is not necessary in that case but it will not do any harm.
 

Informatix

Expert
Licensed User
Longtime User
Ok and also can u please add an extra variable for LineNumber separatly? Because i want to use this future insted try catch and i want to know which line is sent error message to that sub
I know maybe line number can be accessable inside exception message but i want an extra and separate variable for that if is possible

Yes but when my app has not any global resources or initializes starter service is necesaary?
Erel could create a class for StackTrace elements. I had to create one in one of my libraries because it is really useful:
B4X:
    @BA.ShortName("ANRWatchDog_StackTraceElement")
    public class StackTraceElem
    {
        final String ClassName, FileName, MethodName, toString;
        final int LineNumber;
        final boolean IsNative;

        StackTraceElem(StackTraceElement STE)
        {
            ClassName = STE.getClassName();
            MethodName = STE.getMethodName();
            FileName = STE.getFileName();
            LineNumber = STE.getLineNumber();
            IsNative = STE.isNativeMethod();
            toString = STE.toString();
        }

        public String getClassName()
        {
            return ClassName;
        }

        public String getFileName()
        {
            return FileName;
        }

        public boolean getIsNativeMethod()
        {
            return IsNative;
        }

        public int getLineNumber()
        {
            return LineNumber;
        }

        public String getMethodName()
        {
            return MethodName;
        }

        public String toString()
        {
            return toString;
        }
    }
 

ArminKH

Well-Known Member
Erel could create a class for StackTrace elements. I had to create one in one of my libraries because it is really useful:
B4X:
    @BA.ShortName("ANRWatchDog_StackTraceElement")
    public class StackTraceElem
    {
        final String ClassName, FileName, MethodName, toString;
        final int LineNumber;
        final boolean IsNative;

        StackTraceElem(StackTraceElement STE)
        {
            ClassName = STE.getClassName();
            MethodName = STE.getMethodName();
            FileName = STE.getFileName();
            LineNumber = STE.getLineNumber();
            IsNative = STE.isNativeMethod();
            toString = STE.toString();
        }

        public String getClassName()
        {
            return ClassName;
        }

        public String getFileName()
        {
            return FileName;
        }

        public boolean getIsNativeMethod()
        {
            return IsNative;
        }

        public int getLineNumber()
        {
            return LineNumber;
        }

        public String getMethodName()
        {
            return MethodName;
        }

        public String toString()
        {
            return toString;
        }
    }
Thank u, any way i'm so intrested,if this future added then try catch will be join to history :)
 

Cableguy

Expert
Licensed User
Longtime User
if this future added then try catch will be join to history :)

Why??? Try/catch blocks are very useful to prevent an app from crashing due to an unset variable or disposed resource, while the feature here presented, as I understand it, will allow an app to proceed even if an (major) error is fired, thus giving the opportunity to the developers to get this error and try to act upon it.
 

ArminKH

Well-Known Member
not sure,but as erel said : If there is a sub named Application_Error in the Starter service module then the default error dialog will never appear.
as i understand by using this future and if LineNumber added then there is not need to use try catch longer,because all errors can be handled in 1 sub
 

Informatix

Expert
Licensed User
Longtime User
not sure,but as erel said : If there is a sub named Application_Error in the Starter service module then the default error dialog will never appear.
as i understand by using this future and if LineNumber added then there is not need to use try catch longer,because all errors can be handled in 1 sub
I don't understand how you can handle all application exceptions in an unique place. You need to know, for example, whether it's recoverable or not depending on the context. A stack trace does not help to decide whether the error can be ignored or not at runtime. Erel added this event for uncaught exceptions, not to handle all app exceptions.
 

ArminKH

Well-Known Member
I don't understand how you can handle all application exceptions in an unique place. You need to know, for example, whether it's recoverable or not depending on the context. A stack trace does not help to decide whether the error can be ignored or not at runtime. Erel added this event for uncaught exceptions, not to handle all app exceptions.
yes you are right maybe i'm confused today ,anyway thank u both for explanation
 

JakeBullet70

Well-Known Member
Licensed User
Longtime User
I know this might be too much but how about a method to get the Android logs for our own app?
 

aaronk

Well-Known Member
Licensed User
Longtime User
'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
' Do something with this error, such send it in a email, HttpUtils2 etc.

End Sub
Just want to confirm..

From what I understand, if my app comes up with a message box like:

upload_2015-10-30_13-52-36.png


It allows the user to press 'yes' or 'no'. If the user presses on 'yes' it will keep running the app. Pressing 'No' will close the app. Will the above code capture that error and allow me to send a email for example when this internal error happens so we know where this error happens (such as viewing the StackTrace for fault finding)?

If so, this new feature is going to be good. Currently as you can see it doesn't tell you anything about that error and I need to just look though the whole app to find why this error come up. This error happens here and there with my app (so the customer says).

Does this also work if the app crashes? Normally crash reports popup in Google Play but the customer would need to send it. Does this work when the app crashes or when a ANR happens or does the above code only work when a internal error happens?

Also, if you use code like the following would that send the crash by email and also send it in Google Play etc since it's set to Return True ?

'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
' code here to send email or code here to send by HttpUtils2 etc.
Return True
End Sub
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I know this might be too much but how about a method to get the Android logs for our own app?
This is already possible with LogCat from the Phone library.

@aaronk if you add the Application_Error sub then this dialog will never appear.

It will work with most app crashes. It will not work with ANRs.

Also, if you use code like the following would that send the crash by email and also send it in Google Play etc since it's set to Return True ?
The problem with this code is that the process will be killed before the mail is sent.
You need to wait for the MessageSent event. You will be able to call the OS default exceptions handler using JavaObject.
 
Top