12
\$\begingroup\$

I wrote a productivity app for Android. It lets you switch system settings, like Bluetooth, wife, screen brightness, volumes, ringtones, mobile data, airplane mode, etc. Unfortunately I have discovered that device manufacturers modify the OS in every possible way, disabling functionality, requesting additional permissions, or making it available only to system apps. I.e. switching WiFi on stock Android requires android.permission.CHANGE_WIFI_STATE permission, but most Samsung devices also require android.permission.ACCESS_WIFI_STATE. Switching mobile data is simply disabled on many devices.

This makes it impossible to predict how my code will work on a particular device, or on a future version of OS. But at the same time, I definitely don't want my app to crash, because there's really nothing worse that an app can do. So in order to be safe, I've been using what is sometimes called a "Pokemon exception handling" (Gotta catch 'em all!):

try {
    //Do stuff
} catch (Exception e) {
    //Log an error, send crash report, etc.
}
//Keep calm and carry on

I know that this is generally considered a bad practice, but I just can't find a better way to handle this situation. I simply can't predict all possibilities of what could go wrong. Most of my methods for executing actions look something like this:

private boolean switchWiFi(boolean state) {
    try {
        WifiManager wm = (WifiManager)getSystemService(WIFI_SERVICE);
        wm.setWifiEnabled(state);
        return true; //Executed successfully
    } 
    catch (Exception e){
        //Give user a notification about an error, rather than crash
        showErrorNotification("Couldn't switch WiFi.");
        if(BuildConfig.DEBUG){Log.getStackTraceString(e);}//Log exception stack trace
        return false; //Execution failed
    }
}

Is there a better way to handle exceptions?

\$\endgroup\$
  • 4
    \$\begingroup\$ I would catch as many specific exceptions as possible and add the pokemon exception at the end to account for unknown problems. This should give you general error handling while also providing specific information for the most recurring cases. \$\endgroup\$ – Jeroen Vannevel Mar 3 '13 at 23:11
  • \$\begingroup\$ But why catching specific exceptions if you don't have specific error handlers? I often see in code a try with multiple catch that does the exact same thing. For me that does not make any sense. \$\endgroup\$ – Guillaume Jul 22 '14 at 15:04
2
\$\begingroup\$

When the called API throws unknown exceptions I don't think that there is other way than catching all exceptions (sometimes Throwables too). +1 Jeroen Vannevel's comment too.

Anyway, a common interface might be able to improve the code a little bit:

public interface Command {

    run() throws Exception;

    String getName();

}

Then, you can have implementations, like WifiSwitcher, and call them one after the other:

final List<String> errors = new ArrayList<String>();
for (final Command command: commands) {
    try {
        command.run();
    } catch (final Exception e) {
        errors.add("Could not perform command: " + command.getName());
        if (BuildConfig.DEBUG) {
            Log.getStackTraceString(e);
        }
    }
}

if (errors.isEmpty()) {
    return true;
}
showErrorNotification(errors);
return false;

(I haven't tested nor compiled the code above.)

\$\endgroup\$
  • 1
    \$\begingroup\$ Interesting point, I'll give it a try. \$\endgroup\$ – Anton Cherkashyn Mar 4 '13 at 21:53
0
\$\begingroup\$

Try sending your caught exceptions to Google App Analytics as an Event (Then it doesn't show up as an App exception).

Here's how to do it easily in Android:

http://tekkies.co.uk/report-caught-exceptions-as-google-analytics-events/

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.