Overall, mobile browsers are an appealing alternative to native applications: They support most modern web standards like HTML5 and CSS3, and you don't have to set up and learn using multiple SDKs. The technical limitations that do exist will hopefully get fewer as time goes on (or get patched otherwise), while performance and stability will improve. Sure, native apps will always have some advantages, but proper debugging tools should not be one of them. Why those were not available for iOS and Android right from the start is baffling to me, it basically threw us back into the stone age of alert-debugging.
I will occasionally use an example script that contains the following function:
myNumber) being 7. It is then supposed to write "The result is 286" on the screen. The function itself has no bugs in it, but it might not be working for a number of other reasons.
1. Native Tools
For iOS you can enable the debug console. Go to Settings -> Safari -> Advanced, set "Debug Console" to "on". This makes a bar appear at the top of the browser. Tapping that bar shows the console. Here all uncaught exceptions are logged, much like they would on MacOS/Windows Safari for example. The buttons at the bottom allow you to filter the messages, but you can not type anything, or interact in any other way.
This would not really explain why our script does not print anything.
You can also use
console.log() in your script to print out messages:
Now we can tell that it's myObject that is null, but only since we already suspected it and put the log there.
It also does not tell us why. For that a stacktrace, or better yet, a step-by-step debugger would be helpful.
error() do the same, just with different icons. There are also a bunch of other functions on the console object, but they all don't seem to do anything. Even
console.trace(), which can be really useful sometimes, doesn't work at all.
The Android Browser doesn't have a console, or any other tools working out of the box. However, I found some apps in Googles Play store that could help.
JS Log is basically a replacement for the js iOS console. It logs messages and uncaught exceptions in the Android notification area. Too bad that it worked very unreliably. On my Android 3 tablet it sometimes didn't log even when explicitly calling
console.log(). On my Android 4 phone it didn't work at all. (So no Google Chrome support either.) Not recommended.
The HTML DOM Viewer is a minimalstic browser (presumably using the default Android browser internally) that also features a console (for logging only), and allows you to inspect the current HTML/DOM state. Unlike JS Log it's pretty reliable, but it's not very convenient to use. I wasn't able to scroll or clear the console, which is already a deal-breaker. The HTML view has no syntax highlighting at all, and longer tags do not wrap, nor can you scroll horizontally. Oh, and it has ads:
Sadly, no real recommandation for this tool either.
D.I.Y.-Console for Android
The minimal requirement for me is to have a (reliable) way to log errors and messages. So I wrote this little script for Android browsers:
Copy this code into your application or put it in an external .js file and load it from your application. It replaces the dummy "console" object of the Android or Chrome browser with one that actually works. You can see the console either by calling console.show() form your code, or by touching the document with three fingers at once. (So be sure to remove the code before your application goes live.) It obviously won't work on devices that don't have multi-touch.
In contrast to the other console implementations up to this point it also supports "trace" and "dir" commands.
This is the so-called debug version, because for some reason the minified version didn't work for me anywhere but the iPad. Of course this only works if you have an internet connection. Otherwise you have to download Firebug Lite and host it yourself.
Firebug will appear automatically:
Firebug Lite on the iPad. Finally a stack-trace in Safari!
You should disable the keyboards auto-uppercase feature, it will save a lot of time while typing.
Viewing HTML is possible, but a bit fiddly because the UI is not designed for touchscreens. Hitting the "+" icon can be an ordeal.
This would explain why the text isn't visible...
The DOM tab doesn't work for some reason. One possible improvement with this approach is to attach a keyboard and/or mouse to your tablet.
If your Android device has an USB port you can also attach a normal mouse.
Of course you can also just pinch-zoom in (when your application allows it), but it's less convinient and may produce minor glitches. Apparently no one has tried to make a touchscreen-friendly version of firebug or something similar. (Well, excluding my selfmade console above.) I'm sure there are other tools like this out there, but I didn't find any really worthwhile yet.
On iPhone it didn't work at all for some reason, but Firebug is pretty much impossible to operate on phones anyway, due to the small screen.
Firebug Lite (debug):
Firebug Lite (minified):
On the iPad, you first have to create a bookmark in the share menu, then edit it using the "Edit" button in the bookmarks menu. Paste the code where the URL would be. For the Android browser it's a bit simpler, since you can edit the URL while creating a new bookmark. Depending on the Android version/browser, bookmarks are added by pressing some star or "+" icon, or by selecting "Save to bookmarks" from a menu.
iOS on the left, Android on the right. Obviously.
Now you just have to open the bookmark while your application is running. This works very well to open Firebug Lite on the iPad, or the DIY console on Android 3. Sadly, that's it. I had no success with Android 2 and 4 at all, and Android 3 wouldn't load Firebug half of the time, or only very slowly. Another problem is that if you need the tool while the document is loading (e.g. for logging), this solution won't work.
3. HTTP Remote-Debugging
Probably the best known of such tools is weinre. Similar to Firebug Lite, it implements a subset of the features of the WebKit Developer Tools. It has now become part of the Apache Cordova project, but there are no official releases of that yet (August 2012). However, you can get weinre "unofficially" here. I'm using "weinre-jar-1.6.1.zip" on a windows machine in my example.
Unzip the jar file, then type on your console (or create a script or shortcut):
<textarea rows="1" style="margin: 0px; height: 28px; width: 100%; ">java -jar weinre.jar --boundHost -all- --httpPort 9090</textarea>
It should print "weinre:HTTP server started at [...]". Then Add the following line to your HTML
<head>, with [...] standing in for your IP:
<textarea rows="2" style="margin: 0px; height: 28px; width: 100%; "><script src="https://[...]:9090/target/target-script-min.js#anonymous"></script> </textarea>
You can also use a bookmarklet (you can get the code at "https://localhost:9090/"), but if you have a dynamic IP it's pretty pointless.
Then open Safari or Google Chrome on your desktop machine and go to "https://localhost:9090/client/#anonymous". There your mobile device should appear under "Targets" as soon as you load your application.
This is what it should look like. When you reload your target application,
multiple targets may be displayed temporarily.
The Network tab is useful if you work with XMLHttpRequests, like this Eclipse RAP application.
I had the occasional problem to get a working connection, and performance can be bad if your application is very complex. Also, hardcoding an IP address in your script is obviously not a good idea, especially if your IP may change often. Which is where we get to...
While the name might make you think Adobe Shadow is completely different tool developed entirely by Adobe Systems, this is not the case. It has some nice little features of its own (like taking a screenshots of a website on multiple devices at once), but for our purposes it's just a convenient wrapper around weinre.
After you have all that, start the Adobe Shadow application and Google Chrome on your desktop, and the app on your device. Supposedly the app should find the server by itself, but I always had to enter the IP manually. Then you have to enter a short pin from your device on the Chrome extension, and you're connected. Your connected devices will all go to the same URL as your desktop Chrome browser, which is cool in theory, but can get really weird/annoying if you just change tabs to quickly look something up.
Now you just have to click the "<>" icon besides any of your listed devices, and a popup with weinre opens.
I have to say that Adobe Shadow isn't much of an improvement over weinre. In fact, with Shadow I had a lot more issues with not getting or even loosing a connection than with just weinre. Also, both Adobe Shadow apps (iOS+Android) have that feature where they reload the page without using cache (useful!) - triggered by a "pull-down" gesture. This can interfere with your application if you work with touch events or vertically scrolling elements. It really annoys me because it's so unnecessary. Dear Adobe, what's wrong with using a button? It's a tool, not a videogame!
I say go with weinre, unless your IP changes really often. And even then, consider that you still have to re-connect the devices (with a pin!) to your desktop machine every time. Also, Shadow does not work on linux.
Socketbug and Firebug Crossfire and remote jsconsole take the same basic approach as weinre. I didn't get around to try them, but they seem to offer less functionality and no significant improvement over weinre. Perhaps one of these tools will come out on top eventually, but for now I recommend weinre.
4. USB Remote-Debugging
This is only possible with Google Chrome, not the default browser. (Chrome is available for Android 4+).
First it is required to enable USB debugging on the phone/tablet: Go to the device settings, select "Developer options" and enable "USB debugging". Then open Chrome (still on the mobile device), open the menu, go to Settings -> Developer tools -> "Enable USB Web debugging".
For the PC(/Mac) a bit of setup is requried. Download and install the Android SDK, specifically the "platform tools" and "Google USB Driver". It's available for Windows, Mac and Linux. Now connect your device to your PC via USB. In the SDK-directory "platform-tools" you can find the executable "adb". To check that the device is properly connected, type "
adb devices". It should appear in the printed list.
Now type "
adb forward tcp:9222 localabstract:chrome_devtools_remote" and open "
localhost:9222" on your PC's Google Chrome. You'll see a gallery representing the tabs opened on the mobile Google Chrome. Select one and you get the usual WebKit Developer Tools. Like with weinre you can use the console and DOM exploring, but now we can finally do step-by-step debugging:
No more trial and error logging, the debugger reveals everything.
Reloading the page on the device does not require a re-connect, and even breakpoints are sustained. There's no noticeable delay.
The Timeline tab works much better now, and there is even more stuff like Profiling.
Because I'm lazy I wrote a little script so I can always get the developer tools opened in a few seconds.
<textarea rows="6" style="margin: 0px; width: 100%; ">@echo off adb devices adb forward tcp:9222 localabstract:chrome_devtools_remote %localappdata%\Google\Chrome\Application\chrome.exe "https://localhost:9222/" pause</textarea>
If your device gets listed here, but the desktop Chrome shows something like "This webpage is not available", then USB Debugging is probably not enabled on the mobile Chrome.
For iOS there is a tool called iWebInspector, which seems to be very similar. However, it's only working with the iOS simulator, not with real devices. More importantly, it's only running properly on Mac OS 10.6 or 10.7, but no later. (Windows and Linux are out anyway.) As such, I couldn't test it and consider it useless by now.
However, it's very likely Apple does not want to stay behind Google for long, so an alternative is arriving soon. Time will tell if it's going to be a match for Google Chrome's remote debugging. Support for Windows or Linux machines doesn't seem very likely though. Bad Apple!
The main issue here is that there is not one solution that fits for all cases and all browsers. The only option I can really recommend wholeheartedly is the remote USB debugging of Chrome, but that's no solution if you have a problem with another browser. If you require only logging you are probably going to be covered, but anything beyond that requires sub-optimal tools like weinre or Firebug Lite. Of those two I can't generally recommend one over the other. See which one best fits your needs.
You can also use a user agent switcher (like this one) to test your application in a normal browser. This works fine as long as you don't have a browser-specific problem, or need any devices-specific features for your testing (like touch events, rotation, etc.).
I can also generally recommend to write unit tests and run them on your mobile devices. That already gives you a lot more security while writing more code. It may be worth another blog post entirely.
If someone has anything to add, please let me know in the comments. I'm more than happy to update the article. I'll also try to keep it up to date regarding new releases like iOS 6 or Apache Cordova.