What's wrong with debugging in Eclipse on Android? [duplicate]
Possible Duplicate:
Seemingly useless debugging environment for Android
I've obviously been spoiled by Visual Studio, because although I'm just learning Android and the Eclipse environment, debugging apps in Eclipse is becoming a serious detriment to further development.
For example, Eclipse will compile this divide by zero just fine:
public class Lesson2Main extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
int i = 1 / 0;
TextView tv = new TextView (this);
tv.setText ("Hello, Android!");
setContentView (tv);
}
}
And then, when it executes it under the debugger, I will get a full screen of useless debug info, non of which actually points me to the specific line containing the error.
The stackTrace is null within the exception ('e') info tree, and it simply states a message stating 'ArithmeticException'. (that's nice, how about you point me in the direction of where you found it!?)
I've looked all over the screen and am baffled that this IDE can't get this right. Does developing with Eclipse resort everyone back to 1991 with printf() like logging at every interval then to track down bugs? Seriously.
Is there a configuration or plug-in that I'm missing to help with this?
I haven't tested this case with XCode, but if the iPhone dev. IDE handles this more like Visual Studio, then no wonder the Android marketplace has so few apps.
I'm excited about Android, but it seems that Eclipse is getting in the way.
Yes, you've missed one of the very important plug-ins for Eclipse called "LogCat". It catches all the debugging logs that your Android program gives, whether it's running on the Emulator or a real phone. The latter obviously requires that the phone be plugged in to the computer, and less-obviously, the setting in Application -> Development -> Enable USB Debugging be enabled.
The LogCat messages give you the full breakdown of what caused the error, including the line number. To open LogCat in Eclipse, go to Window -> Show View -> Other -> Android (one of the folders in the list) -> LogCat. Then dock the LogCat window somewhere where you can see it easily, and Eclipse will remember that location and open it up again next time your start it.
(Sometimes LogCat and the Emulator get disconnected from each other. The simple way to fix that is just to close Eclipse and the emulator, then restart them both.)
(There's too much to say in a comment, so I'm writing this up as an answer.)
You can configure Eclipse to stop on exceptions that are caught, uncaught, or both. By default, Eclipse will break on any uncaught exception, and will ignore all caught exceptions (i.e. anything that is snagged by a try/catch block).
Things get a little weird for Android because you're running in an application framework, not a stand-alone application. As you can see from the stack trace posted above, the exception was actually caught by ActivityThread. This means that your initial exception is considered "caught", and won't trip Eclipse's break-on-uncaught handling until ActivityThread re-throws it. For this reason, the stack you see in the debugger when it stops is nowhere near your code.
Since you know you're getting an ArithmeticException, you can have it break on "caught" instances of that exception, and it will stop at the point of the throw. (Don't have it break on all caught exceptions -- you'll be hitting "resume" endlessly.)
As far as the logging being "late", if the debugger let the program continue to execute until the logging happened, you wouldn't be able to debug at the point of the throw.
I get the following stack trace in logcat:
03-31 17:01:11.272: ERROR/AndroidRuntime(205): java.lang.RuntimeException: Unable to start activity ComponentInfo{MyClass}: java.lang.ArithmeticException: divide by zero
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2401)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.app.ActivityThread.access$2100(ActivityThread.java:116)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.os.Handler.dispatchMessage(Handler.java:99)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.os.Looper.loop(Looper.java:123)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.app.ActivityThread.main(ActivityThread.java:4203)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at java.lang.reflect.Method.invokeNative(Native Method)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at java.lang.reflect.Method.invoke(Method.java:521)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at dalvik.system.NativeStart.main(Native Method)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): Caused by: java.lang.ArithmeticException: divide by zero
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at MyClass.onCreate(MyClass.java:40)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
03-31 17:01:11.272: ERROR/AndroidRuntime(205): ... 11 more
This is crystal clear. Look at the causing exception in line 14 of the stack trace and it says: Divide by zero. That is what you have done wrong. The next line says: at MyClass.onCreate(MyClass.java:40) This would be the line the exception occurs in. I don't get what would be difficult, or useless about this. How would VS present this?
For weeks after starting Android development, I was frustrated by the lack of information I found in the LogCat window. I would put Log messages in my app and never see them, and I knew my app was throwing exceptions but I never saw those either.
Finally one day I figured it out: my LogCat window was showing the wrong device. I usually have two or three Android devices connected to my computer at any given time, and LogCat was showing one of those other devices. To change this you have to display the Devices window and select the device you want in that window.
I find this to be an example of laughably bad UI. Here I am looking at a LogCat window and nowhere in that window is there any indication as to what device's logs I'm looking at. I have to know enough to open a totally different window and select the device there. I literally wasted weeks of time before I figured this out. You'd think that LogCat would default to all devices, or at least, automatically switch to the device you most recently launched an app on, but it doesn't. If you are banging your head against your desk wondering why LogCat is so useless, maybe this is why.
You are experiencing a typical problem of developing with a physical device as opposed to a piece of software on a machine.
It will point you to the specific error (Post the info and we can show you) Just look for your package names in the error it will show where the exception was thrown.
You should also use breakpoints to step through the process and see what happens the DDMS debugger should meet all your needed requirements.
And yes you should use logging Log.i(TAG, "Info: " + x);
You can't predict everything that happens and as your code base grows you will be glad you started doing this early.
精彩评论