Apteligent crash monitoring for mobile apps allows developers to better understand the issues that cause fatal exceptions or errors. With this type of insight into app performance, you gain a broad perspective on some of the issues that plague apps and frustrate developers. As it turns out, over 85% of all crashes on Android can be categorized into five types:
If you’ve ever built an app on Android, you’ve seen this error, so no surprise that it’s #1 on our list. The best way to avoid this exception is to assume the worst, since the most common reason for it is data going out of scope or getting garbage collected, then getting referenced later.
For this reason, the top location for NPE’s is the Android onResume() method. When the app goes to the background, it may have to get rid of some memory, losing various references along the way. To avoid this, save your data from the onPause() method into a more persistent layer like a local database or cache, then pull it back out within onResume().
Some other areas to look out for are data from intents, sensor data (i.e. camera, GPS, etc) and broadcast receivers (both data sent to them, as well as receivers that have gone out of scope). A good rule of thumb is to null-check data received in these areas before operating on it, and handle the null case appropriately to ensure the best user experience possible under the conditions.
This is one of the more frustrating exceptions for developers because it seems to happen at random – and to some extent, that’s true. OOM errors occur when the operating system needs to limit the resources being used, particularly your app’s heap allocation. This is done to keep memory free for higher-priority operations, usually OS-driven requirements.
As devices get more powerful and ship with more memory, memory management gets easier, but if you look at the number of devices in the market today, you can’t rely on your users having the latest and greatest. Even then, you still need to be careful with your resources.
One of the biggest causes of memory leaks is keeping a reference to an object longer than it’s needed. This causes your app to eat up memory that it may not even need to be using, and you hit your limit sooner.
Be sure to recycle objects like bitmaps as soon as you can – they are a common reason for memory use since images can be large, especially with today’s higher resolution screens. If you end up with too many in memory, it can start to trigger OOM exceptions. Image thumbnails are common within ListViews, where you should also be sure to utilize available tools like viewHolders as described here.
If you find your app needing a lot of memory due to its nature (always always always make sure you are adhering to proper memory standards), then you can request additional heap memory from the operating system in your manifest file with the attribute
However, keep in mind that this is a soft request, and it may or may not be granted. Furthermore the amount of increased memory will also be variable. To learn more about analyzing your app’s memory, check out this blog post.
As you may imagine, this one has to do with one or more windows within your app – but it’s usually seen when working with dialogs.
Note: The original Android dialog objects have been deprecated for a while, so if you haven’t switched to DialogFragments yet, now is the time.
If you’re just getting started with Android, you may create a dialog via getApplicationContext() when you should be creating the dialog in the activity’s context, rather than the application’s context.
Beyond that, anything that changes the context of the activity will generally cause issues. For instance, showing a dialog after an activity’s onPause() method is called, or a screen rotation occurring while a ProgressBar is being displayed. For these, it’s always best to save your instance state and reset the context references on any changes that change the state.
4. java.lang.IllegalArgumentException (extends java.lang.RuntimeException)
The cause of IllegalArgumentExceptions is the most varied of those on the list, but still a common cause for crashes. The simplest is, well, your argument is illegal. Usually the compiler will keep you from making too many mistakes here, but there are gotchas.
Make sure your castings are always correct and be smart when referencing resources, since many UI methods accept both strings and integers. The compiler doesn’t know (or care) which one you’re trying to do.
For example: if you try to display an integer within a label, the OS will look for a string resource instead that may or may not exist at runtime.
Some other pitfalls worth mentioning:
- Forgetting to add an Activity to the Manifest. Again, this is a runtime exception so won’t be caught by the compiler
- Loading UI elements directly from a background thread
- Trying to use a recycled bitmap
This one only applies to those apps that leverage a SQLite database, but this is the most common way to persist (especially larger amounts of) data throughout the application’s lifetime. The reasons for this exception vary, and always look at your crash report’s stack trace to determine the exact cause, but a few tips to keep it from appearing:
- Always use the provided database helper to create, open and upgrade the database (ex: if you modify the schema). This is the most stable way to determine or catch issues with read/write permissions, SD card problems and other OS/device-level scenarios.
- Use a single SQLite connection to avoid race conditions or scenarios where relational data is dependent on other data that may have been changed, modified or not inserted yet. Relational errors will throw the SQLiteException.
Any SQL syntax errors or issues with prepared queries (unknown column, table, etc) will also throw the SQLiteException. It’s always best practice to use try/catch blocks around your queries just in case a syntax error slips through. Use Apteligent’s Handled Exceptions to make sure even the caught exceptions are logged for you to resolve any issues.
This is by no means an exhaustive list of why an app may crash, but can hopefully give you an idea of what to look out for during development and testing. Most importantly, just because it works for you doesn’t mean it will work for all of your users on all their different devices, operating systems and setups. By integrating an SDK into your app that includes real-time crash reporting functionality, you can gain full insight into the performance issues that your users run into. Leverage these tools to get bugs resolved before they affect your users, ratings, and revenue.