Catch all exceptions and send them by e-mail - android

In my app I want to catch all types of exceptions and send reports by e-mail. For that I'm using global try catch block. But now I need to recognize exception by type. How can I do it?
try{
...
}
catch (Exception e){
//Here I need to recognize exception by type
send(Error);
}

Why you don't simple send the whole stacktrace?
send(e.getStackTrace())
It not only contains the Exception type but also where (file, class, line) it occurred.
Additionally, you can also simply use the toString() method.
See the java doc for further information

Instead of rolling your own error logging and reporting mechninism I strongly recommend you use ACRA Its free, open source, and supports sending error logs to email. I have used it for quite some time and it is very good.
This will give you all sorts of information such as phone make, model, resolution, free memory, as well as a full stack trace of the error. Its by far the easiest way to get quality error reporting into an Android app.
The best part is it takes all of about 5 minutes to get setup and integrated.

e.getClass() // will give you Class object
e.getClass().getName() // will give you class name
However if you know the class names already you can use
if(e instanceof A)
{
// some processing
}
else if(e instanceof B)
{
//some processing
}
else
{
//
}

Related

How to handle different kinds of errors in Retrofit Rx onError without ugly instanceof

I would like to know your ways to handle different kinds of errors (like http exceptions, no internet connection exceptions etc) in retrofit Rx onError without using instanceof like it's proposed here: How to handle network errors in Retrofit 2 with RxJava or here: Handle errors in Retrofit 2 RX
In kotlin I will simply make some extension functions for each kind of throwable to do whatever I want.
But I am forced to use Java in the project. Any nice suggestions?
is the approach to build some kind of error handler like this:
public interface ErrorHandler {
void handleError(Exception e);
void handleError(HttpException e);
void handleError(NullPointerException npe);
}
good? I know it is not because every time i need to handle another specific error I am forced to change interface, so it is violation of Open Close Principle. But I can't figure out any solution .
cheers
Wojtek
The compiler determines which method to call, rather than the VM. So the class you've described won't solve the problem unless you check instanceof first and cast the paramter to the correct type. Otherwise you're going to get handleError(Exception e) every time.
But I wanted to create an answer not for that reason, but to argue that having only one error handler is actually preferable in many cases, not a liability. Oftentimes in java we end up in awful situations like this:
catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("No such algorithm: RSA?", e);
}
catch (NoSuchProviderException e) {
throw new IllegalStateException("No such provider: " + ANDROID_KEYSTORE_ID, e);
}
catch (InvalidAlgorithmParameterException e) {
throw new IllegalStateException("Bug setting up encryption key for user credentials: ", e);
}
catch (KeyStoreException e) {
throw new IllegalStateException("Bug setting up encryption key for user credentials: ", e);
}
catch (IOException e) {
Log.w(TAG, "Exception setting up keystore for user creds. They won't be stored.", e);
}
catch (CertificateException e) {
Log.w(TAG, "Exception setting up keystore for user creds. They won't be stored.", e);
}
Having only one error handler gives us the ability to lump many types of exceptions together. You can see in this code, there are exceptions that should never be thrown, exceptions that can really only be the result of a bug in the code, and legitimate exceptional states that we need to handle. I find this messy, and would prefer to say:
if (e instanceof NoSuchAlgorithmException || e instanceof NoSuchProviderException) {
Log.wtf(TAG, "What the heck is this?", e);
throw new IllegalStateException("This is some kind of weird bug", e);
}
else if (e instanceof IOException || e instanceof CertificateException) {
// This can happen sometimes, track event in analytics and perhaps
// try some alternative means of credential storage.
}
else {
// At least here the app won't crash if some unexpected exception occurs,
// since we're trapping everything.
}
I don't think it's such a bad thing to be able to lump unexpected failures together and handle them in a more user friendly way than crashing the app. Even if it's just a bug, better to track it in your analytics framework behind the scenes than bomb the user out of the app. So many crashes in Android apps are actually completely recoverable, but we don't go around catching Throwable in every try/catch statement because it's a lot of extra code.
The proper OOP way to avoid chained ifs or catches is polymorphism. You can define several custom exception classes exposing common interface that is enough for a single handler to process.
Suppose you need to divide errors in two groups: recoverable and not recoverable. Then your base exception class (or interface) shall have abstract method isRecoverable() that you override in each subclass. Then there will be only one if in your handler: if (e.isRecoverable()) { ... } else { ... }.
The downside is that you have to wrap all standard exceptions into your custom ones at places where they are thrown (you have to catch them).
The right choice will greatly depend on your task, though.

Can't reproduce android crash

Android keeps on reporting crashes from users which I can't reproduce on my phone.
I can find the lines which seem to be incorrect:
cursor.moveToFirst();
elechs=cursor.getString(2);
elecls=cursor.getString(3);
gass=cursor.getString(4);
waters=cursor.getString(5);
cursor.close();
if (elechs.length()!=0){
elechdb=Double.valueOf(elechs);
}
else {
elechdb=0.0;
}
if (elecls.length()!=0){
elecldb=Double.valueOf(elecls);}
else {
elecldb=0.0;
}
if (gass.length()!=0){
gasdb=Double.valueOf(gass);
}
else {
gasdb=0.0;
}
if (waters.length()!=0){
waterdb=Double.valueOf(waters);
}
else {
waterdb=0.0;
}
elecldb=Double.valueOf(elecls);
gasdb=Double.valueOf(gass);
waterdb=Double.valueOf(waters);
If I look at the code, it doesn't make any sense.
I think I forgot to delete the last three lines. First I check the string. If the string is empty it will store the value as zero.
The incorrect last three lines will also try to make a double if the cell is empty. This cause a lot of crashes. However not on my machine.
I believe that it shouldn't be possible to make a of an empty cell.
Does anyone know why this error doesn't crash my phone?
Your best solution is probably just to remove the problematic lines that shouldn't be there anyway, preferably add actual error handling around calls to Double.valueOf() in case the input is completely malformed (there may be inconsistent behaviour if the cell is empty, but if it says "hello world", everything will crash), and release an update.
Since the users are getting NumberFormatException, you should catch the exception and perform appropriate action when it happens.
if (elechs.length()!=0) {
try {
elechdb=Double.valueOf(elechs);
} catch (NumberFormatException e) {
// Perform error handling
}
}
If the users are getting NullPointerException, you should check if the strings are null before checking for their lengths.
If the data is put in by the user, you should do both of the above to avoid future problems.

How can I send an exception manually with Crittercism?

I'm using the android crittercism library and trying to send a report when I catched an error level exception.
But I can't find the documentation on how to do that. Is this even possible? If so, how?
They temporarily moved the feature into beta. If you e-mail support they'll enable your account for handled exceptions. Below is the sample Android code:
try
{
throw new Exception("Exception Reason");
}
catch (Exception exception)
{
Crittercism.logHandledException(exception);
}
Just in case you need it, here is sample code on iOS:
#try {
[NSException raise:NSInvalidArgumentException
format:#"Foo must not be nil"];
} #catch (NSException *exception) {
// Pass it on to us!
[Crittercism logHandledException:exception]
}
I'm the co-founder and CTO of Crittercism. If you send me an awesome email, I can enable it for your account. I'm rob[at] :)
Crittercism.logHandledException(new Throwable("test"));
You don't actually have to throw the Exception (or Throwable, in this case).
It will appear under "Handled Exceptions" on Crittercism website.

stack trace and variable values

Is it possible to get variable values included in a stack trace? I have just started using bugsense which emails the stacktrace to me and I wonder if there is some way in my code to put the variable values into the stacktrace output
Not by default, you have to do it by yourself:
The stack trace will only tell you about the involved line of code (where the Exception is thrown) and the execution stack.
But nothing prevents you from catching the Exception and to include some debug information in the message:
try {
...the code...
}
catch (Throwable t) {
// Here, we catch any Throwable (Exception but also Error such as OutOfMemory
// or NoClassDefFound), which is *absolutely not suitable* for
// anything else than debugging.
// You can (should, actually) make this catch statement more specific
// depending of the Exception or Error you are facing
// Dump your variables here:
final String message = "myVar=" + myVar;
// The statement below rethrows the original Throwable and adds your
// own message to it
throw new RuntimeException(message, t);
}
Or to put a breakpoint in the catch { } statement to inspect the state of your application at that stage, but as I understood it may not be applicable in the case you are describing.
(By the way, I suggest you add the tag "Java" to your question. This way it will also be visible by the Java community of StackOverflow)

How to programatically hide Caller ID on Android

on Android phones, under Call -> Additional settings -> Caller ID
it is possible to hide your caller ID. I want to do that programatically from my code, but was not able to find a way to do that.
I searched through
android.provider
android.telephony
for 2.1 release and was not able to find it.
Has anybody successfully solved this issue?
Thanks in advance. Best regards.
Here I will describe two approaches I tried.
1.) It is possible to display Additional Call Settings screen from your application. Although it looks like it is part of the Settings application, that is not true. This Activity is part of the Native Phone Application, and it may be approached with the following intent:
Intent additionalCallSettingsIntent = new Intent("android.intent.action.MAIN");
ComponentName distantActivity = new ComponentName("com.android.phone", "com.android.phone.GsmUmtsAdditionalCallOptions");
additionalCallSettingsIntent.setComponent(distantActivity);
startActivity(additionalCallSettingsIntent);
Then user has to manually press on the CallerID preference and gets radio button with 3 options.
This was not actually what I wanted to achieve when I asked this question. I wanted to avoid step where user has to select any further options.
2.) When approach described under 1.) is executed in the Native Phone Application, function setOutgoingCallerIdDisplay() from com.android.internal.telephony.Phone has been used.
This was the basis for the next approach: use Java Reflection on this class and try to invoke the function with appropriate parameters:
try
{
Class <?> phoneFactoryClass = Class.forName("com.android.internal.telephony.PhoneFactory");
try
{
Method getDefaultPhoneMethod = phoneFactoryClass.getDeclaredMethod("getDefaultPhone");
Method makeDefaultPhoneMethod = phoneFactoryClass.getMethod("makeDefaultPhone" , Context.class);
try
{
makeDefaultPhoneMethod.invoke(null, this);
Object defaultPhone = getDefaultPhoneMethod.invoke(null);
Class <?> phoneInterface = Class.forName("com.android.internal.telephony.Phone");
Method getPhoneServiceMethod = phoneInterface.getMethod("setOutgoingCallerIdDisplay", int.class, Message.class);
getPhoneServiceMethod.invoke(defaultPhone, 1, null);
}
catch (InvocationTargetException ex)
{
ex.printStackTrace();
}
catch (IllegalAccessException ex)
{
ex.printStackTrace();
}
}
catch (NoSuchMethodException ex)
{
ex.printStackTrace();
}
}
catch (ClassNotFoundException ex)
{
ex.printStackTrace();
}
Firstly I tried just to use getDefaultPhone(), but I get RuntimeException
"PhoneFactory.getDefaultPhone must be called from Looper thread"
Obviously, issue lies in the fact that I tried to call this method from the Message Loop that was not the Native Phone App one.
Tried to avoid this by making own default phone, but this was a security violation:
ERROR/AndroidRuntime(2338): java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.provider.Telephony.SPN_STRINGS_UPDATED from pid=2338, uid=10048
The only way to overcome (both of) this would be to sign your app with the same key as the core systems app, as described under
Run secure API calls as root, android
I'm not sure if this is a global feature, but Australian phones can hide their number by prefixing the caller's number with #31# or 1831. This may not be the perfect solution, but a prefix like this could possibly work for your requirements during coding.

Categories

Resources