Debugging Web Apps on Android’s Mobile Browser

For some unknown reason, Google did not include a debugger in their native browser, at least for versions up to v2.3.x. I don’t have a phone that supports a version greater than that, yet, so I can’t speak about the latest releases. Unfortunately this can be a huge productivity killer. The good news is there is a solution – you can debug the native Android browser using what’s called the DDMS, or Dalvik Debug Monitor Server, and the ADB, or Android Debug Bridge. I can also tell you this works great.

Yes, it’s true that JavaScript development forces you to have an armada’s worth of tools, tricks, libraries, phones and browsers. This is just another hammer to place into your growing toolkit. Debugging via ADB was good news for me since I do native Android development and I already have the software installed when I installed the full Android SDK. If you don’t do native development then it’s a real pain.

But, if you want to do your best to deliver bug free apps, then your best bet is to install at least ADB. I believe, but I’m not 100% certain, that you can this without having to install Eclipse along with the entire Android SDK. Yes, I agree that installing the entire SDK would seem entirely ridiculous and complete overkill for mobile web development, especially if you are not using Eclipse as your primary IDE. I’m aware that in the past I’d seen a few stand-alone versions of this floating around for both Windows and Linux. I’m not even remotely certain about Mac’s. If you do know something about this, then I encourage you to please post a comment.

How to use ADB. My suggestion, once you’ve installed it, is to filter by the tag “console” if you are using Android v2.x and above.  Instructions on how to do filtering can be found in the ADB link below and scroll towards the very bottom of the page.

Caveat: You will have to install the Android USB device driver on your machine in order for ADB to work.  And, you will also have to have a USB cable that will connect your device to your dev machine. The drivers are different for every device. I’ve included a link to Google’s device drivers below. On a related note, for several of my Motorola Androids I had to go directly to the Motorola website to find a device driver that finally worked.

Another Possibility – Adobe Shadow! You should also be aware of a very cool development from Adobe called Shadow. As of today, I believe you can still download it for free from Adobe labs. I mention this last because, well…I haven’t tried it out. However, my good friend Kevin Hoyt, from Adobe, says it’s very, very promising. And, it’s supported on both Mac and Windows. As I write this I’m thinking that I really do need to download it and test drive it. If you have tried it, then post your thoughts…don’t by shy!

References:

Adobe Shadow + sneak peak video

Google’s ADB

Android Device Drivers

Google’s Guidelines for Web app developers

Auto-resize Dojo Mobile Charts on Orientation Change

The best I can tell, Dojo’s dojox.mobile.Charts2D do not auto-resize on their own when the phone’s orientation changes. I posted a question on how to get around this on the Dojo Community Forum and never got an answer. So, I had to cobble together my own solution.

I have to point out that the functionality I built by hand is inherent in Flex and Silverlight, and you wouldn’t even bat an eyelash thinking about this. So, from a productivity standpoint I spent about double and maybe even triple the time I should have needed in order to sort through why things weren’t working as they should, and to build my own best practice for handling it. 

I do consider what I built as a hack, so caveat emptor. It should at least give you a good starting point to improve on what I’ve already done. There are some important things to note.

  • Here’s a sample demonstrating the functionality: https://andygup.net/samples/realestate/
  • Dojo does not provide any State properties on the View. So, I had to build that.
  • Dojo does not provide any way to bind a dijit to a mobile View. In other words, this enables the Chart to take action automatically when something happens in the View. Check…yep, I bolted that in.
  • Dojo, as far as I know, does not provide a way to detect when the phone’s orientation changes. So you have to listen for that at the window object level. I’m fairly certain that the pattern I used is not completely reliable across all platforms, but it’s what I had to work with. So, I built that too.
  • I also had to detect if there was no orientation change prior to a View transition. This was so that I didn’t unnecessarily redraw the chart and make it appear to flicker. This check was important because my chart is in a secondary View. There seems to be a bug in charts redraw() function in that the chart may self destruct if you try to redraw it from a different View.
  • There’s a bug in the Android native browser that passes the previous orientation event object to the listener. You actually have to set an event timer so that you retrieve the final, and most recent, orientation event object.
Here’s how you initialize the chart. In this case, I’m using a pieChart. This snippet also includes the html markup:
pieChart = new com.agup.PieChart("chart1","statsView").pieChart;

<div id="chart1ParentDiv" dojoType="dojox.mobile.RoundRect">
        <div id="chart1" style="width:100%; height: 350px;"></div>
</div>

Here’s the PieChart Class that I built to encapsulate the functionality I described above:

dojo.declare("com.agup.PieChart",null,{
    pieChart:null,
    orientationChanged:null,
    constructor:function(chartDiv,chartView){
        this.pieChart = this._createChart(chartDiv);
        this.orientationChanged = false;
        if(chartView)this._setTransitionListener(chartView);
        if(chartView)this._setOrientationListener();
    },
    _createChart:function(chartDiv){
        //create the chart
        //Had problems with using just HTML markup, so creating it here and piping to DIV
        var pieChart = new dojox.charting.Chart2D(chartDiv);
        //set the theme
        pieChart.setTheme(dojox.charting.themes.PlotKit.blue);
        //add plot
        pieChart.addPlot("default", {
            type: "Pie",
            radius: 100,
            fontColor: "black",
            labelOffset: "-20"
        });

        pieChart.isVisible = false; //NOTE: this is a new public property that we inject

        return pieChart;
    },
    _setTransitionListener:function(/* DIV of dojox.mobile.View where chart resides - typeof String  */view){
        var test = dijit.byId(view);
        var pieChart = this.pieChart;
        dojo.connect(test, "onAfterTransitionIn",null,
                dojo.hitch(this,function(){
                    pieChart.isVisible = true;
                    if(pieChart != null && this.orientationChanged == true)var time = setTimeout(function(){pieChart.resize()},700);
                })
        );

        dojo.connect(test, "onAfterTransitionOut",null,
                function(){
                    pieChart.isVisible = false;
                }
        );
    },
    _setOrientationListener:function(){
        var supportsOrientationChange = "onorientationchange" in window,
                orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

        window.addEventListener(orientationEvent,
            dojo.hitch(this,function(){
                var pieChart = this.pieChart;
                var orientationChanged = this.orientationChanged;
                if(pieChart != null && pieChart.isVisible == false){
                    orientationChanged = true;
                }
                if(pieChart != null && pieChart.isVisible == true){
                    orientationChanged = false;
                    var time = setTimeout(function(){pieChart.resize()},700);
                }
        }), false);
    }
});

The problem with JavaScript Obfuscators and Minification – Tracking down errors

JavaScript obfuscators and minifiers do their job well. In fact, some obfuscators have anti-debugging features. However, if you are a legitimate developer building applications against one of these libraries, chances are you’ve gotten an indecipherable error such as “z=null line 14300” and it brings your development efforts to a halt. Error messages like this provide no useful information on what the problem really is, or give any hints on how you might be able solve it. You’ve probably even looked at the jumbled source code in a last ditch attempt to make some sense out of the error. And, whether it’s your own library or a mainstream ones as jQuery or Dojo, it doesn’t matter. The amount of productivity lost because of these errors in probably very large, not to mention the frustration it causes.

I hope the the developers of these obfuscators are reading this…because I have a proposed solution to the problem.

Now, I want to start out by mentioning that I fully understand why obfuscators exist for reasons such as source code protection and decreasing download size. What I propose takes this fully into account, yet makes your library developer friendly in a secure way:

During the obfuscation process create an index file that maps each variable, function and class to a real line number and store this file in a web folder.  Then create a small html file that lets you search the index and return the real line number. Provide an option for return the variable, function or class name, too.

The concept is that if there is an error, like the  “z=null line 14300” I mentioned above, developers can then at least have some hope of narrowing down the general area of the code where it might be occurring.

The bonus is, if you own an obfuscated commercial library, now your tech support people can also look up the general area where a customer might be having a problem. For security reasons you don’t have to share the index file, But, even then, there isn’t enough information in it to de-compile the library. Now, if I post my error to the forum:  What is “z=null line 14300”? Tech support will be able to tell me that I’m missing a custom property on a widget’s HTML DIV element. It’s a win-win situation.

What do you think?