Why the Google Play Console of my Production app crash reports (located in "Android Vitals" / "ANR and Crashes" and then select any crash to see a stack trace) contains a lot of ORs in the Stack Trace?
What does it mean? Which of that 12 methods actually caused the crash? Why the report so unclear?
Is there a way to get exact method name and ideally the line number in the report? (I have added mapping file under "Deobfuscation files").
The reason is that you are using Proguard for minifying and obfuscating your code (so far so good), and Proguard reuses the same method names as much as it can (i.e. as long as the signature of the methods are different) to minimize the number of letters it has to use. So the minified code contains most likely a dozen of methods with the name "a" in each class, and the stacktrace only gives you the method name, not its signature, so it's unfortunately impossible to know which one of the dozen "a" methods is being called, hence the deobfuscation tool gives you all the possibilities.
You can customise the Proguard configuration to avoid so many conflicts and hence make it easier to debug for you, but that will be at the cost of your app's size.
Edit: Use the -useuniqueclassmembernames flag to avoid these ORs. You can check the ProGuard manual for more details.
I had the same question some time ago:
Strange stacktrace reported by Google Play Console.
In my case i could notice that only one of the functions in each group could be the right one beacause the others where not invoked inside the "above" function.
I think this is a protection method against reverse engineering.
Related
We have a shared library which we do not wish to share the symbol names with anything - including Crashlytics.
As such we really want either:
1. The base address at which each .so has been loaded or
2. Module-relative addresses shown in addition to or instead of absolute addresses in stack traces
Either of those would allow us to produce post-processing tooling (ala addr2line, etc) that turn the crash report into something meaningful without sharing library symbols externally.
Is there some way already to get at this information with Crashlytics? If not, any chance it could be added in the near future? What about the crash reporting via Google Play Console?
Crashlytics does not offer a viable solution for this right now. Our symbolication is all or nothing. Thanks!
In my application I'm using a class Cs for doing the logging part.
It already has a DEBUG field which is set to true/false depending on the build type.
Everything is working good so far but I want to improve this a bit so I'm trying to find way to automatically comment these lines. This will avoid some problems that might appear due a log.
Ex:
1. StringBuilder messages = getSomeMessages()
2. Cs.e(TAG, messages.toString());
When line 2 is commented the app won't crash if the messages is null.
Also if I remove these lines in release but keep them in debug version it will be hard to detect the errors from stacktrace because the lines number won't match anymore.
My question is: It is possible to tell Proguard to comment all the lines which start with some characters (Cs in my case)?
Thank you
Also if I remove these lines in release but keep them in debug version it will be hard to detect the errors from stacktrace because the lines number won't match anymore.
For starters, your assumption that commented lines would make it into the compiled class/dex files is incorrect. This will not differ between debug and release builds.
Secondly, by optimising and/or obfuscating, Proguard will most likely modify your code in such a way that line numbers will no longer match up with your original source. That's exactly why it generates a mapping file (generally just mapping.txt): so that a stack trace can be de-obfuscated (or: retraced).
When line 2 is commented the app won't crash if the messages is null.
StringBuilder messages = getSomeMessages()
Cs.e(TAG, messages.toString());
Correct. But if you're after improving your code and its robustness, why not guard the log with a null check?
For example: only log something if there are actually messages:
if (messages != null) Cs.e(TAG, messages.toString());
Or: log some indication that there were no messages:
Cs.e(TAG, messages != null ? messages.toString() : "<empty>");
I'm not sure what kind of logger Cs wraps, but consider leveraging the functionality of Android's own Log class. That is, if you're really logging an error for development purposes, using Verbose or Debug log levels will make more sense. These are automatically stripped away (at resp. compilation time and runtime) and as such you don't have to worry about accidentally generating an exception in your production builds when logging.
Alternative, you can also easily wrap any debug logging with a check for the auto-generated BuildConfig.DEBUG flag - it sounds like you're already doing that.
How do I retrace my Proguard Android App with the Crash report in Google Analytics. A few examples as follows:
Note: when crash reports are done by the User with the Google App Console, I can use retrace OK with the mapping.txt file.
Examples (from Google Analytics Behavior Crashes and Exceptions)
RuntimeException (#a:a:-1) {main}
IllegalStateException (#f:a:-1) {main}
NullPointerException (#MainActivity:M:-1) {main}
NullPointerException (#a:l:-1) {main}
NullPointerException (#al:run:-1) {main}
I just started gathering statistics, and ran into this myself. From an exception that happened to me on a not-obfuscated apk, the syntax seems to be:
exception-name (#class-name:method-name:line-number) {thread-name}
class-name: If this is obfuscated, then you're usually stuck, because the package name is not reported. Sometimes you might be able to find the class, like in your 'al' example, because most packages wont have that many classes (search for '-> al').
method-name: If the class-name isn't obfuscated (some class names have to be excluded from obfuscation for the app to work) you can try to look up the method in the mappings.txt. Often there'll be multiple methods with the same mapping (but different calling signatures). As you can not distinguish between them, then you'll have to check them all to see if they could have caused the exception.
Line number: this of no use since it is is obfuscated (-1).
Conclusion: with the standard reporting, most of the time you wont be able to find out what caused the exception. There seems to be the possibility to set up a custom exception parser, possibly allowing you to include the full stack frame. I have not tried this yet, but found a promissing description in this answer.
Obviously with code, errors can occur anywhere. So without having try/catch blocks all over the place (which as I understand it is major overhead) how do I allow errors to bubble up to the application level and then handle them there? Or at the very least, record the error somehow for troubleshooting? I found information on an product called ACRA, but the setup instructions are geared for Eclipse projects. I am using Mono for Android in Visual Studio 2010.
That's a bit of an "It depends" question.
The appropriate handling of an errors is going to depend on what the recovery strategy needs to be, how much information you want the user to see etc.
I wouldn't worry how many Try/Catch blocks you use - just use them wherever you need to handle an error that gets thrown - if they're everywhere, your strategy is probably wrong.
It terms of logging and later interrogation, you can log caught errors using the Android.Util.Log class.
These can be interrogated (provided you're debugging on your own device) using Logcat.
There's some more info on logging and Logcat here.
Found this project that writes crash info to google docs. Android Crasher
I understand there is the LogCat view to check the messages logged but I can't make sense of it.
When debugging (I use Java primarily) I've been accustomed to stepping over each line of code and finding out the exact point where the program crashes and then doing something about it.
How can I do this with Android development? Is there a way to precisely locate the line which is causing the application to crash?
I can't understand what to make of/how to read the LogCat messages and when I try to step over (using the F9 key or the 'Debug' option in Eclipse) it keeps opening new tabs for inbuilt classfiles (like Instrumentation.class etc) and after pressing F6 a few times over again the app crashes showing 'The application has stopped unexpectedly. Please try again'
Can someone tell me if there's something to be done in a way that I'm not doing here?
Thanks!
Btw if it helps, here's the generated log:
http://pastebin.com/EaqaWUdS
You are using a resource id that doesn't exist at line : 93 of com.site.custom.ModAdapter.getView(CustomListProjectActivity.java
--EDIT : add explanations
You will read a logcat stack trace in the same way as you did in Java : read bottom up and the culprit is the last line of your classes (before the code gets into the android sdk code).
You can do it the other way around, and start from top, stopping at the first class of yours and discarding android classes.
The same reasoning applies when debugging : step into your methods if needed and step over all methods of the SDK unless you want to debug them (and usually you don't, if you really suspect a bug inside the SDK, check the source at grepcode to see the inner mechanics of the android sdk class you are interested in).
Sometimes it gets difficult to track bugs on android, especially for widget layout related bugs because you can only see the code that is executed by the android platform, no code of your is executed, only your data are read from an xml file for instance. If something breaks here, it can be harder to debug. In that case, apply the dichotomy method : remove half line, if the bug doesn't show up, then readd your lines, remove half of them, etc...
It is the same like in java. Basically you need the sources to open the java files instead the class files. Google shows you how to add the sources.
Basically you debug android while staying in your own classes. I barely look into the android classes as the most issues are, of course, located in my own classes.
So just debug like you already do but don't step into methods/classes you don't own unless you have the sources added to your sdk. Even if you have, there might be some classes that aren't open source, so you can't step into the sources there. (Basically all Google API classes)