Wednesday, December 23, 2015

A new ParkInfo Mobile using Ionic & AngularJS

It's been three years this week, since I wrote my first mobile app: ParkInfo Mobile. And this week, the new one is still under wraps for some branding and color choices, but is functional. ParkInfo Mobile 2.0.0 should be in the app stores in a week or two, replacing my Christmas 2012 edition.

I'm not particularly sentimental, but it's a big step forward in a few ways. Let me share a few interesting changes in the new version, and lessons learned by writing it.

What's New


First and perhaps largest: It's written in Ionic, and thus AngularJS. This is a paradigm shift from jQuery Mobile, in which the DOM and global variables rule everything. The code is broken into a bunch of bite-sized segments: each panel is one HTML page and one paragraph of code, though some of them refer to the "global" functions for some commonly-used functions and needs.

It doesn't use an onboard JSON file, but HTTP hits to a web service. The original ParkInfo Mobile had a JSON file included, which could be used for searching and estimating distance without using the data connection. But it kinda sucks. Including the polygons made the file about 100 MB and would crash any phone, so it didn't happen. Using only the centroids means that we can estimate distance and direction to the centroid; for a city park that's not too shabby, but for a 500,000-acre preserve the centroid could be miles away and be misleading. The new one uses a web service to query the database; it's swift, simple, and effective. Better, the web service can accept a hint as to your origin lat-long and return the closest point to each of your results, greatly improving the accuracy and usefulness of the results.

The performance is fabulous, and look and feel is smoother. They said that AngularJS and Ionic have decent performance, and I know that jQuery Mobile kinda sucks... but dang, it's really that much improved. Navigation is smoother, more fluid. The default styling doesn't include so many drop shadows and rounded corners, so the whole thing feels more bare... if a bit cartoonish with those colorful buttons. (Like I said, the colors and branding stuff is still pending.)

The UI for offline tile caching is improved. The underlying technology is much the same: Cordova's file API, with ngCordova wrappers. But the UI for caching is greatly improved.
  • Caching by current map view is disabled, in favor of two new options: cache around a street address, or around your current location. This is a lot more useful, generally speaking.
  • "Passive caching" will cache your map tiles to device storage while you browse the map. If a specific address or your GPS location don't fit what you need, just let the cache populate as you pan and zoom.
  • While downloading tiles, the UI doesn't block you with a modal, but starts up a progress bar and lets you go on your way. Downloading 1000 tiles can take a few minutes, but you're not waiting around.

Lessons, Hacks and Limitations

 

Some of the things that went less smoothly:

When you need two controllers to know each others' state, AngularJS is a pain in the neck. The cache panel needs a list of map layers, but it's the map controller which has the Leaflet object and the L.TileLayers. Ultimately I really did need to separate out the layer listing into a Constant where it could be seen by both. Angular's all about not believing in globals, but dogma had to take a seat while pragmatism prevailed.

Ionic's sidemenu  is cute, but not flexible. It took me only 2 hours to come up with a thing that our clients will demand that it cannot do: put an icon in the top-right corner, which varies on every page (different icon & link, or none). I tried everything from position:fixed to negative top margins, even tried a nested view in the titlebar, and it's a no -- that titlebar isn't part of the dynamic part of the view. So I went the way I knew I would eventually, started with a blank template where each page has its own titlebar so we have maximum flexibility. I knew it would happen since our capricious designers are the ones calling the shots, but it irked me that those "copy-paste my code, and you're a mobile developer" articles basically have someone copy-paste the sidemenu starter, knowing that it paints you into a corner less than 2 hours later.

I've still not wrapped my head around Services and writing my own promise chains. The web service calls would ideally be a Service instead of a function defined in $rootScope. But a service which accepts callbacks as parameters, which makes a $http call and hands off to those callbacks just eluded me. After a day, I needed to just get past it so I gave up and went with a $rootScope function that accepts a pair of callbacks, without a promise involved. Similarly, I couldn't figure out a promise chain to wrap a dynamically-generated list of potentially thousands of Cordova File API calls and perform them sequentially, so I went with my old "i+1" method. Then again, other reading indicates that a chain of a few thousand promises maybe isn't such a hot idea anyway...

Debugging is a real nuisance when there aren't any globals, and you can't see into scopes private data. Keeping everything in tiny secret boxes, doesn't do well toward being able to type MAP.getCenter() into the Firebug Console to find out something so simple -- and that makes all debugging just that much slower. I need to put in some effort, into figuring out techniques for debugging AngularJS apps aside from console.log() inside these isolated black boxes.

Angular-leaflet-directive is pretty limited, and I've had to do a bunch of work to it myself. I'll likely fork it and start adding my own patches into it in a more concerted manner. But some of the adjustments I've discovered and invented include:
  • You must use in in a ion-view with overflow-scroll="true" or else the map will cease to receive click events if you navigate away from it. It's not just the map, it's something about the underlying DIV. Those "copy-paste your first mobile app!" postings don't mention stuff like that, eh?
  • It doesn't support popups, so I added a popup bit to it.
  • It doesn't propagate bounds changes back to the scope, only center. Fixed that. 

 

The Future of MobileMapStarter


My second mobile app was actually stripped down from my first: ParkInfo Mobile's map/cache/page functionality was stripped down to form MobileMapStarter.

Last year after I presented MMS at FOSS4G it got some popularity, but I've been less than 100% satisfied with it. It's jQuery Mobile so it's slow, the cache UI isn't so hot, etc.

But here we have a new framework with a map, panels, and caching. If I strip this down a bit, it's a fresh new start for "MobileMapStarter, Ionic Edition". Schedule permitting, maybe I can have that done in a couple of weeks.



Monday, November 30, 2015

Ionic and AngularJS

In my personal time, I have one mobile app that I manage: BattleTech Calculator. It's a calculator for an old 1980s board-and-dice game, makes a lot of the tedious math move more quickly so we can focus on pretending to blow up our giant robots.

I went with Framework7 for this one, on grounds that it looked like a winner. It's HTML/CSS with some DOM manipulation capability similar to jQuery. It has basic routing, doesn't look half bad. And BTC being a non-work app, I figured there's no harm if Framework7 turned out not to work out well.

Trouble With Framework7


Ultimately, it did not work out well.

First was the freezing/crashing issues. I thought it was just my phone because the other two folks didn't have any problem... until they reported that they did. Just switching between tabs in the usual fashion, it would freeze solid and you'd have to terminate the app and start over.

Second was a reported visual rendering bug. I could never replicate it myself, but I got several reports in the Store after one update, that when they switch tabs the old tab's content would be visible on top of the new tab's content. Again, I couldn't make it happen but the reports were consistent enough that, combined with the freezing, I decided to try something new.

And that's not including some documentation inaccuracies, the $$ and $ bug, and a few other quirks and shortcomings.

Ionic Framework is based on AngularJS, and on the web side of things that's a totally new thing for me. As I described in prior blog posts searching for a HTML framework, Angular is designed around concepts like modules and components, instead of the designer-driven daily-spec-change chaos which typifies a lot of our web-map applications. But in this case, I did have a solid idea of what I wanted, and even a working prototype in my old version.

It took some getting used to... but Ionic/Angular kinda rocks.

DOM manipulation and AngularJS


DOM manipulation is out the window. Because of data-binding on the form widgets, the ng-show and ng-hide directives allow other stuff to show and hide as the form is manipulated, allow for recalculations to happen any time the form is changed, etc. The result is more intelligent form widgets and less code and code repetition.

Old, a separate piece of logic to show only the applicable table:
var which = $(this).val();
$('#tab-meleehitlocation span.meleetype').hide();
$('#tab-meleehitlocation span.meleetype-'+which).show();

New, the table is intelligent as to its visibility condition:
<div ng-show="viewdata.meleetype == 'punch'"> Lorem Ipsum </div>

Old, remove the highlight from all rows, add to this one:
$('#tab-meleehitlocation span.meleetype-punch div.row').removeClass('hit').filter('[data-roll="'+rolled+'"]').addClass('hit');

New, the row knows when it should be highlighted:
<div class="row" ng-class="{ highlighted:viewdata.outcome == 2}">
This data-binding and implicit state awareness is a key point of what makes AngularJS what it is, but felt very foreign and difficult to wrap my head around at first. But once it sunk in... I'm impressed. I think that AngularJS's "state propagation intelligence" could achieve any sort of unpredictable DOM manipulation we could need, in a more intelligible fashion than our old jQuery implementations.


Ionic Framework and Ionic View


Ionic Platform itself is a set of tools based on Cordova/Phonegap, but adding their special sauce of CSS utility classes, button colors, a set of icons, etc. And yet, I was allowed to ignore and override to suit a few specific needs, e.g. a SVG dice icon, in lieu of FontAwesome which did work just fine.

So as far as the HTML/CSS flexibility, Ionic really did work well here.

And then there's Ionic View, Ionic's test-deployment platform. It's similar in theory to the Phonegap Developer App:
  • Your testers download the Ionic View app and sign in to the Ionic View service, and see a list of app which they have been invited to test;
  • You type ionic upload to upload your content to the Ionic View servers;
  • Testers re-sync your app, and re-launch and test. No code signing, OSX builds, etc.
This significantly accelerated my testing cycle, even as one single person on a weekend project. The uploads are as fast as Xcode compiling it and far faster than dropping the APKs onto Google Drive and waiting for them to sync. And since it's over data (meaning, while I'm at home, over wifi) I can test it as I walk around, refill my coffee, etc. without ADB pitching a fit and forgetting to reconnect the device, etc.

So yeah, Ionic's non-Angular nature... also a winner.


What It Means For BattleTech Calculator

The new version of BTC isn't finished yet; I have one whole panel to go. But let's look at bits of logic and overall code volume, and see what Ionic has helped me to improve.

https://github.com/gregallensworth/BattleTechCalculator/tree/master/www
https://github.com/gregallensworth/BattleTechCalculator-Old/tree/master/www

  • The very large HTML is broken into partial views. This keeps me visually focused, which is great if you have "situational ADD" aka being interrupted all the time.
  • HTML volume is currently 609 lines compared to 1125 lines. Add another 125 for the last page, and this is still a 40% reduction.
  • JavaScript code volume is 295 lines (not counting that unfinished panel, maybe 150 more) compared to 522. This would be a mere 20% reduction... but still 100 fewer lines of code. This is largely due to the removal of DOM-fussing since AngularJS takes care of that automagically.
  • Almost every line of code is simply more readable: default settings are declared in the controller instead of as checked attributes, code is more logical since it doesn't read from fields and do the DOm shuffling.
  • The code is even easier on the eyes, since $('#') is absent.
  • The app runs very smoothly for the most part, under Ionic View, on my old Galaxy S3. Smoother than with Framework7.
  • The app hasn't crashed once yet, in a few days of development and testing. This counts for a lot!

What it Means For Work


Virtually all of our work is websites, and the designers use mobile-unfriendly layouts with floating panels and the like. So Ionic won't be doing a lot there; it can scrape by for websites, but support for IE isn't so hot. But for the few mobile apps we do each year, we have a winner.

For websites, I am starting to get into the feel of AngularJS. If we can combine this with something visual like Bootstrap, it could be very neat. The big challenge there, of course, is that our clients and designers don't have Bootstrap on the brain so we end up rewriting large parts of the visuals anyway. But for a general system of DOM management and data management, AngularJS is looking pretty sweet, and I'll be working with it some more on personal projects.

Tuesday, October 13, 2015

Census blocks and attributes: An easier way

Has it really been almost 5 months since my last posting? I've been doing plenty, but not a lot of it is so inspired but also of wide enough interest that I've felt it relevant to share.

But if you work with census data, this may save your day:
https://github.com/greeninfo/CensusShapefileMaker

It does a day's worth of census downloading, joining, trimming, and calculation... in 10 to 15 minutes (most of that being the FTP download).

 

History

I created this for a client. Her specific use case, is to have census blocks for a whole state (though sometimes one county), joined to a few attribute tables so we have statistics such as number of people, number of people who are black/white/etc, number of people who are under 18, and so on. We'd then derive some statistics such as "number of people under 18" which itself means adding up 8 attributes then dropping those 8 since we really only wanted their sum. And of course, we only want a dozen or so columns but those attribute tables are huge, so she'd drop hundreds of columns with unintuitive names such as p61ia She would do this process in ArcMap and it would take an entire day or sometimes two, and was highly error-prone.

So, I sat down with MCDC's Dexter and the USCB FTP and figured things out.

 

A few tricks and paths

  • Dexter allows one to specify only specific attribute fields to be downloaded, and allows downloads of both decennial census and annual ACS. This is great, since it makes the CSV files so much simpler to parse: they have the fields you asked for.
  • I did try having ogr2ogr perform the join between the CSV and the shapefile -- after a couple of hours it was obviously not getting anywhere. So the technique is to open the shapefile via Python ogr and loop over records, assigning their attributes. For performance, it loads the whole attribute table into a dict which sounds bad, but in reality works fine since modern laptops have 8 GB of RAM.
  • Good ol' ogr2ogr is still used for stripping out attributes, e.g. the stock shapefiles have extra attributes we didn't care for. This could have been done in Python ogr as well, but was already done in ogr2ogr.
  • We wanted a YOUTH field indicating number of people under age 18, but the Age By Sex table has that broken over 8 fields. So at the merge phase, that youth sum is what it loads from the CSV in lieu of the 8 individual fields.
  • Median Household Income (MHHINC) comes from ACS and not from decennial, and comes at the tract level instead of the block level. Fortunately, the hierarchical naming convention for the GEOID makes it dead simple to figure out which tract corresponds to a given block. During the merge phase, the first 11 digits of the tract are used to look up the corresponding tract -- easy.
  • As an afterthought, the thing can also strip down to one specific county (identified by its FIPS code, in the hierarchical GEOID) if you didn't want the whole state. This is done at the very end, since frankly the processing is so fast that the seconds you'd save by pruning it first aren't worth the programming trouble.
So yeah, if you work with census data a lot you may find this one useful. Enjoy!


Wednesday, May 27, 2015

Marker "spotlight" for Leaflet and for Google Maps API

A client really liked this spotlight effect demonstrated for ModestMaps. It calls out the selected markers, without hiding the other markers or forcing the user to perform a new search. And hypothetically this would be a great feature for the legend, to mouse over the legend and have the matching markers "light up"


But it didn't exist for Google Maps API (which the client uses), nor for Leaflet (which we use on 95% of our other projects). So I spent an afternoon coding this up:
https://github.com/greeninfo/MapSpotlight

All in all it was pretty easy, and even fun. I got to read about the HTML5 Canvas which I rarely get to work with outside of some charting libraries, and got to learn about Google Maps API's OverlayView capability, and the analogous iLayer interface for Leaflet.

So yeah, go grab a copy and highlight some markers. :)

Tuesday, April 28, 2015

First experiments with Unity

I'll deviate briefly from my usual topic of maps, GIS, and web-GIS, to something different...

I started playing with the game engine Unity. I wanted to do something after work that felt creative, and completely different than anything I've done before. And video games using Unity, sure fits that: no authentication and scrubbing user input, no SQL databases, no rendering PNG tiles. Rather, a empty world with gravity and solidity, and objects that have intelligence. Neat stuff, very educational.

My first project is a spinoff of the classic Unity tutorial, Roll-a-Ball. Being myself, I couldn't just follow instructions and I had to takre it off in my own more complex direction. I added a concept of the board tilting to screw with gravity, added a behavior that when you get all targets it creates more and increases the tilting, and so on.

It's not a million-dollar idea, just experiments. So I thought I'd share with other Unity newbs.
https://github.com/gregallensworth/DrunkBubble

Sunday, April 12, 2015

New Leaflet Control: L.Control.BasemapBar

Some time back I created a basemap-selection control for use with Leaflet, which is quite nice. It can switch between standard XYZ L.TileLayer basemaps, Google basemap choices, and Bing basemap choices provided you load the APIs and layer plugins.

Check out this screenshot, then check it out on Github:



So today I polished it up a bit, removing the requirement for FontAwesome and adding some documentation, and released it on GreenInfo's Github page. We think it's a really nice tool forr switching between basemap options. It's functional, it's attractive but not gaudy, and it's flexible to handle all of our basemap needs.

Enjoy!

Monday, March 30, 2015

New Leaflet control: Credits

Lately, I've been polishing up more of these old Leaflet Controls that I've created over the last year. Here's another one.

https://github.com/gregallensworth/L.Control.Credits

This one's pretty simple: supply text and a URL and an image, and it generates a cute interactive icon in the lower-right corner. There are various ways to make credits in your Leaflet map, this is the one used by GreenInfo Network and it's quite nice.


Book Review: Phonegap for Enterprise, by Kerri Shotts

Kerri Shotts is a member of the Phonegap mailing list, who quite frequently posts helpful advice. I appreciate her contribution to Cordova/Phonegap community. She's even written a few books, such as PhoneGap 3.x Mobile Application Development Hotshot which I have. So a few weeks back, I jumped at the opportunity to get a free copy of Phonegap for Enterprise, on condition that I review it.

One of the best parts about reading someone else's perspectives on programming, is that they have different angles and use different tools. As a result, I may not use their techniques but will learn about some tool that fits a need better than my current tool. And as far as I'm concerned, every "Oh, I didn't know that!" moment is a gem. And this book had plenty of those.

Super Short Summary


A good book, including an overview of technology choices and general and specific notes about how to make your application more secure... but also more likeable. It's definitely not a cookbook nor a how-to, as much as considerations and options which may apply to your application.

It's full of outside-the-box ideas, and full of options and links to other resources so you can take those ideas and run with them in your own direction. Phonegap for Enterprise is a worthwhile read regardless of your Cordova skill level.


Openings


The book opens with the usual What is Phonegap? sort of introduction. It then moves quickly into a discussion of how to store your backend data and options for where to put your business logic, and an overview of what goes into an application. This isn't novel stuff, if you've written web services before... until she brings up some alternative angles on business logic and on database storage.

She mentions a database-in-cloud service called Parse, and considers doing business logic in the database (PL/SQL) as opposed to in external code (PHP or Node). Leveraging you're database server's PL instead of using a second-layer language? It's certainly an interesting approach, and she does describe the balance of the two approaches. Definitely food for thought here.

She wraps up this introductory chapter with discussion of planning out the application: what fields do a Task and a Person have, and what Persons can view and edit what Tasks? If you're new to web services then thinking this stuff out beforehand is something that really helps a lot, and yet it's a phase often skipped - it's good to see someone advocating for that.

Security


Chapter 3 puts the carriage before the horse a bit, to touch on security. It's rare that anyone discusses security in the opening, and I appreciate that she does.

This chapter touches on security, considering the usual concepts such as using SSL but then worse-case scenarios such as man-in-the-middle attacks, and forged copies of your app. She touches on novel ideas such as hardcoding a certificate fingerprint into the app for better security, and even really-crazy stuff like calculating HMACs for your requests so the server can ensure that they requests are likely to be from your app instead of an AJAX trawlbot or a session replay. She points out the impossibilities of protecting your source code, the possibilities of someone falsifying your app and hijacking your user's network, and more.

Individually you can take or leave each idea, and some you can't really do anything about. But as a whole they present a rich and thought-provoking set of considerations which a busy developer often skips over until the end... when they forget to do it at all!


Building Foundations


Chapters 4 and 5 proceeds to the building of your web service. Kerri describes the basics of REST and also some of the realities of how we do things instead of true REST, then gets into some code bites to get started on setting up your URL routing and authentication.

This part I found somewhat baffling and dense. It jumps around a bit, and leaves out details of authentication beyond mentioning the benefits of using a third-party service such as OAuth yet stating that we had settled on using a local password hash using PBKDF2

But getting past that, Kerri does illustrate the beauty of Passport. The details of session.createSession() are implemented inside Passport and you could just as easily be using an OAuth service to generate those tokens which you're later validating with Passport. And again with considerations as being a theme here, the benefits of a dedicated OAuth service over a local password database are discussed.

Now, her specific take on REST as following the HATEOAS concept feels a bit overwrought to me, as if she's trying to reinvent SOAP. Given that any API change would implicitly come with app changes to both the UI and the programming, it's not the case that the app could auto-configure itself if endpoints change anyway. So ultimately I'm not convinced that this is the way I would do things.

But though HATEOAS is over-the-top for this application, Kerri's coverage of it is still food for thought, if we intended to construct web services which are subject to change and intended to be consumed by something other than an app which we control. You don't even need a mobile app in the works for this to have interesting possibilities.


Cordova Considerations and UI Considerations



Chapters 5, 6, and 7 get really into the Cordova-specific considerations and techniques for your app. And this is some good stuff.

The device can lose and regain its network status. Your device could be backgrounded and then terminated before you had a chance to save state to LocalStorage. You can store stuff in SQLite and encrypt it. There are freemium services to both act as Push Notification gateways and Push Notification SDKs. And she covers these expertly: succinct and yet thorough with good advice.

Mobile UIs have different expectations than desktop UIs, and Chapter 8 really tries to cover it all.  It includes a tutorial on MVC, and observer-based data-binding frameworks. She points out UI considerations and modern HTML5 tags, and mentions a few options for charting. (she forgot to mention Highcharts, my favorite.) It's a bit scattered since a complete discussion of options could fill a lifetime, but as usual rich in provocative thoughts and in options to find your own way.

This set of chapters was my favorite of the whole book (as was Chapter 3), in terms of gems of wisdom.  The brevity of my review of this whole one third of the book, really doesn't do it justice. There's way too much for me to summarize, so buy the book and read it yourself. ;)

All In All


It's a bit dense at the start, but it's not meant to be a cookbook. It's about ideas and considerations you that may not have crossed your mind when you did your first apps. It's so rich with "Other Resources", that if you think her specific ideas aren't for you, give thought to the considerations she brings up, then read those other resources and do it your way.

Phonegap for Enterprise a worthwhile and educational read, for people of any skill level with Cordova.

Monday, March 23, 2015

More Github and leaflet awesomeness: L.TileLayer.Cordova

What a busy week! Found a cool Leaflet plugin, wrote a new Leaflet plugin, ... and finally put the polishing touches and refactoring onto a pet project from almost two years ago!

https://github.com/gregallensworth/L.TileLayer.Cordova
This Leaflet layer plugin extends L.TileLayer to add on-device caching of tiles, then the ability to switch between online mode (from web using the URL given) and offline mode (the on-device stash). Utility functions are provided to calculate tile pyramids, to accept arbitrary lists of XYZ ordinates,to view the cache usage, and to empty the cache.

If you make Leaflet maps for use with Cordova or Phonegap, you'll be interested in this!

Friday, March 20, 2015

Another neat Leaflet control: L.Control.BoxZoom

Yesterday,  I was also asked by a client to create a box-zoom tool. Their end users don't know about using the Shift key, and at any rate they prefer the visual aesthetic of a visible, clickable button to make a one-time box zoom.

I was quite surprised to find no ready-to-deploy ones. And I was pleased with Leaflet for making subclassing L.Control so darn easy! About 90 minutes later, I had this:

https://github.com/gregallensworth/L.Control.BoxZoom

Not a lot to say about it. It's a single button, clicking it will let you perform a box zoom one time, at which time the control will turn itself off again.

Cosmetically, you could configure the HTML a bit. The default one on Github, simply uses a background-image and a included SVG icon. The live, deployed one for this client uses a FontAwesome <i> tag, and your own could use Twitter Bootstrap icons or whatnot.


Enjoy!

Thursday, March 19, 2015

Neat Leaflet plugin: History

A client today asked for a History tool in Leaflet. The idea, is that some Forward and Backward arrows are on the map, and these will track back through the "history" of your map extent: pan, zoom, pan again, ... then back up to that previous extent.

It doesn't come up often, but this particular client had it on a prior project I did and they really like it. But does it exist... for Leaflet?

Yes, it does! Thanks to Chris Scott there's a History control for Leaflet. It's tiny and functional, has no frills and no surprises.

Thursday, March 5, 2015

Weinre and GapDebug


Weinre Is Awesome

For the last year-plus I have been using weinre (Weinre website) for debugging my Cordova apps.

Basically it's a UI very similar to Chrome's F12 tools: DOM browsing, CSS editing, JavaScript console, etc. ... for use with remote mobile apps. You insert a line of JavaScript into the client code and it loads a whole bunch of hooks and behaviors, which you can then talk to via that UI in your browser. Voila: type alert('Hello') into your browser, and your app has a popup alert.

Unlike the remote debuggers provided with various SDKs, it is not platform-specific. The very same browser window can debug apps on Windows Phone, Android, iOS, ... And that's pretty slick.

Weinre is about the greatest thing since Firebug, for figuring out why your Cordova app is misbehaving. For Cordova-based apps in particular, an online actively-on-the-phone debugger is important, since JavaScript failures just do nothing.

But Now There's GapDebug

The down side of weinre, is that it's a network thing. You need a server running weinre, and both your phone and your browser connect to it. If your phone is using its mobile network and your PC is on your home wifi, then you need a third-party server e.g. at work or on an EC2 instance. If you're running both the phone and your PC on the LAN, Windows Firewall can be a nuisance and prevent the phone from connecting (the only symptom being that your phone never shows up on the list of remote connections).

Genuitec embraced the cable, with GapDebug. (Genuitec Website)

It's basically the same idea as weinre: a local service that communicates with your phone and app, with a browser-based UI featuring a CSS editor and JavaScript console and all. It's all the awesome of Chrome's F12 tools.

The first big difference from weinre is that GapDebug works over the cable. I have my phones plugged in via cable anyway, so I can push code updates and also not have the battery conk out, so adding a cable is nothing new.

The second big difference, is that weinre requires that you place a <script> tag into your HTML, then remember to remove it for production. GapDebug uses the android:debuggable flag in AndroidManifest, so I'm equally likely to forget... but then again I make changes to AndroidManifest less often than to index.html so an outstanding change there is noticeable.

The third big difference, is that GapDebug works over the cable... and not over the Internet. Weinre's ability to work over the Internet makes it fill a slightly different niche, when the need arises.

Why Choose?

So, weinre is obsolete? Well, no. They hold slightly different places.

For my day-to-day debugging on my own phones, plugged in via cable anyway, GapDebug is my tool of choice.

But what if I want to debug someone else's phone? Then I stick the weinre <script>tag into the HTML, ship to the beta tester, then open up my browser. Their copy of the app calls home to weinre, and I can work with it right there. If she fires up Skype, I can even talk with the beta tester and see her phone while I fuss with it remotely. Can't do that over a three-foot cable!

My advice: Use both. :)