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.
Related
When looking at logcats in Android Studio 3.1, sometimes the "metadata" portion of some log lines are omitted. For example, the leading portion gets removed, which might look like:
06-06 17:55:39.364 9929-9945/com.ttm.zapp I/com.ttm.zapp:
Everything that follows that prefixed data in the log line is printed, however. See the image below for a better example.
Is this a bug? And if not, is there a way to disable this (what appears to be) "grouping" behavior?
The grouped log statements are printed at the same timestamp. If you type adb logcat into the terminal, you can see the formatted logs there.
That being said, there is an issue being tracked on Android Studio here to make this logcat behavior a configurable option.
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.
Android app submission says, remove any logging before submission. Have a few question on this one
Is System.out.println considered as logging? How can I disable it across the app without having to remove it on by one
Tried android:debuggable="false" inside manifest, but eclipse says "Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one"
I have some third party jar files that shows Log statement when I test my app. How can I remove them, considering I don't have the source.
Suggestions are highly appreciated.
I'm sure you've come across the fact that you can do the if(GLOBAL_VALUE) trick, because your logs are already there!
Therefore, my suggestions is to use Proguard; http://developer.android.com/tools/help/proguard.html
The following proguard.cfg chunk instructs to remove Log.d calls.
-assumenosideeffects class android.util.Log {
public static *** d(...);
}
You can do it for other calls like Log.i, Log.e, etc based on the value you put there!
As for your Jar, if it is referencing the Android Log system, ProGuard should take care of that.
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)
Try the following:
Create a HelloWorld application.
Add a Log statement to the end of onCreate:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("HelloWorldActivity.onCreate()", "setContentView() completed");
}
Place a breakpoint on the Log statement.
Run the app in the emulator and note it works and step to see the Logged entry in the LogCat window of Eclipse.
Change the HelloWorldActivity to extend from ListActivity instead of Activity.
public class HelloWorldActivity extends ListActivity {
Run the app in the emulator again and note it fails to reach the Log statement.
My question is NOT why this fails. My question is, how would you go about debugging this failure? All I see in the Eclipse Debug pane is a RuntimeException. I see LogCat has a bunch of messages, but it's huge and I've searched it but can't find anything to indicate what's wrong or where in my code the exception happened. I can't find a way to display the message inside the RuntimeException or a stack trace to know which line of code initiated the exception.
I assume there must be better ways to use the tools to find errors, but I'm new and can't seem to figure out a better way to debug besides wrapping everything I code in a try/catch. I would have expected to find a message in LogCat generated by the throwing of the exception. I would have expected the Debug window to allow you to inspect the exception's contents. I'm not saying that such techniques don't exist, I'm saying I'm having trouble figuring out as a beginner how to debug and asking what techniques do exist and how do I use them?
So, simply put:
How would you find this error if you didn't already know what was causing it?
What techniques would you use to find out the root cause?
How would you go about inspecting the Exception's details?
Generally, how do you find problems in your Android code using Eclipse?
Multiple suggestions and discussion are welcomed. :)
I would have included my LogCat contents, but it's so large that's not reasonable. You should be able to easily reproduce this yourself, so I left it out. It is possible something is in LogCat to help me, but because it's so large with even running a small program, I would need a hint as to what to search for and how to interpret it when hitting an exception thrown from an API call. I see other posts that state something should be in LogCat, which while might be true, I'm not finding anything myself. If you think something should be in LogCat, please run the test yourself and copy the lines into your response that I should be finding.
Thanks.
========
Summary techniques list so far is as follows:
Invasive Techniques:
1. Place a Toast in code locations where you want to see you you've executed.
2. Place try/catch around code where you think there's a possibility of an Exception being thrown.
3. Comment out code and recompile and retest.
Non-Invasive Techniques:
1. Use the debugger. Breakpoints, variable inspection...
2. Monkey stress tester.
3. Download Android source library.
4. Use LogCat filters to see if a "Caused By" is listed.
Unclear if Available:
1. Debug version of Android library that has additional logging, assertions or other additional help.
2. Ability to inspect an Exception in Eclipse through the Debug pane or other techniques.
3. A way to define a more global try/catch exception handler.
4. Ability to debug through the Android library source code.
Not Available:
1. A non-invasive way to view the contents of an Exception or where the Exception happened.
hey,
Ineresting question. Well, first tip, you can filter what logcat tells you. For instance, you make it just show you errors by clickin in the red (e).
It also tells you where the error happened if you run your app in debug mode. It can either point you directly to your code or to android sdk. Knowing what android package caused the error is a big help.
These two just pop into my mind. hope it helps!
I was running into the same issue and found the following by Steve H. that helped out:
What happens is that when the debugger
is attached, the exception logs don't
get posted to LogCat until you
terminate the application from within
the Debug perspective. This happens
because the application doesn't
actually crash until the debugger
detaches. – Steve H Mar 31 at 15:47
------ yup, that did it. Now I see the same exception. AFTER I let the
program run through it's full crash
and exit process. It should display
that info when it halts my program and
brings up the IDE debugger screens.
Not leave me wondering and wasting my
time with more clicking around.
Eclipse has a long way to go it seems
to compete with the likes of Visual
Studio. Let's hope my patience for it
outlasts my project. Thanks for the
feedback. :) – Sebastian Dwornik Mar
31 at 17:35
Link to Question: What's wrong with debugging in Eclipse on Android?
Generally if anything throws an exception then you should probably be catering for that situation anyway, however putting try/catch blocks is a decent way of finding the specific problem.
I've found that if you don't put something in the catch block then you can't evaluate the exception in the watch variables window in eclipse. So i always put a Log call in and set a break point on that line.
public void onCreate(Bundle savedInstanceState) {
try{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}catch(Exception exception)
{
// put break point on line below so you can evaluate exception in debug mode.
Log.e(TAG, "Set content exception "+ exception.getMessage());
// note some exceptions return null on getMessage();
}
Log.d("HelloWorldActivity.onCreate()", "setContentView() completed");
}
So if your stack trace is huge then this will help. Other developers have also found that getting the source code for the sdk means you can view where the error is thrown in the main sdk code. I've not done this though.
Exceptions not caught with try/catch are errors and break the normal flow of the program.
Running in debug mode is just clicking in the bug button. I don't know if there are any "special" debug libraries. But when working with android, all "libraries" are open source so you can pretty much view anything.
The good thing about debug mode is that when an error occurs, your app is frozen right in the limbo when the error occurs. You can set set breakpoints, change your code on the fly while your program is running, which is great (Well, you can't make drastic changes like changing a method name).
The way you treat bugs and errors in android, however, can be a bit different from .NET, since the model in each one is different.
When programming to windows, apps work like small islands. You have a much direct control over the code flow (ie: you can call a modal dialog to freeze codeflow while a user inputs some data) and you can make a totally functional program using just one thread. In android almost everything runs in it's own sync. And your app must be prepared to handle stuff like receiving a phone call in the middle of execution. So, you can apply this model to debugging also: Errors (that happen due to unforsen circumstances) tend to propagate much more than in other development ambient. The way those errors are handled is different too: this is apparent when you realize that your app still runs even after throwing an exception.
Some more useful tips:
You have a very powerful tool called Monkey, a stress tool that generates "pseudo-random streams of user events such as clicks, touches, or gestures, as well as a number of system-
level events".
LogCat indicates you the "cause" of the error. The line usually starts with Caused By. If you're interested in the cause rather than the consequence, you can further filter your error reports looking for "Caused by".
Last but not least, I find the old method of commenting lines and see what happens very useful to figure things out.
hope it helps