It’s been no secret to any of my friends and Twitter followers that I’ve been looking for new opportunities, especially in the Android space. Sometimes the harder you look for something the harder it is to find and sometimes the best things happen to you almost by accident.
In April I saw a tweet show up in my feed about MobileDevCamp NYC. For those that don’t know, it’s basically “get a bunch of developers, designers, and other assorted geeks together and see what they can build in 24 hours.” I first heard about it less than a week before it was scheduled but there were tickets still available so I signed up.
We split up into 14 teams of about six people each. The team I was on built a cross-platform YouTube playlist app for iOS and Android. One of the other members of our team was a developer for the social media site Patch.com. They collect community-specific news and information for individual towns and communities using local editors, writers, photographers, and videographers that actually live in or near the towns they cover.
Apparently something about me impressed him because the next day I received an email from the company inviting me to come in for an interview. Three days later I was downtown interviewing with several people including part of the team in Dublin, Ireland. To make a not-very-long story shorter, an offer was made and an offer was accepted. Starting May 23rd I will be joining Patch.com as a mobile developer working on a project I don’t think I can talk about yet (cause I don’t know if its been publicly announced yet.) I’m very excited to be working with this team. This will be the first time I’ve worked at a large company (frankly, anything more than a half-dozen people is large for me) and the first time I’ll be working with designers, product managers, etc, etc.
As for this blog I’ll eventually move it to a new location. I don’t know yet if Patch.com has a developer’s blog (or wants to start one.) If so, I hope to start blogging there. Otherwise, I’ll have to figure something else out. I still plan on speaking at CodeStock on June 3rd and 4th and at MADExpo on June 30th – July 1st (you can still register for MADExpo here.) Anything after that I’ll have to play by ear.
I tweeted a while ago about how if life is full of up’s and down’s someone was having a lot of fun with all my up’s. With this move, I’ve started to reclaim my up’s.
Since my Eclipse installation blew up I’ve been using the IntelliJ IDEA Community Edition for Android programming. Like many others I prefer working with a dark editor background instead of a blinding bright white background but I found there are very few places you can find pre-made IntelliJ color schemes and there’s no place like http://studiostyl.es for IntelliJ. So I translated a couple of my preferred Visual Studio color schemes (Son of Obsidian and Ragnarok Blue) to IntelliJ.
You can download either or both color schemes from my Dropbox. Both SonOfObsidian.zip and RagnarokBlue.zip contain an XML file of the same name; put the XML file in your home\.IntelliJIdea10\config\colors directory (you will need to restart IntelliJ before it will pick up the files.) After you restart IntelliJ, go to File->Settings->Editor->Color & Fonts and select the scheme you want to use from the Scheme name dropdown. Both schemes use the Consolas font.
Translating the schemes was pretty straightforward with only a couple of gotchas. First is you have many more customization options in IntelliJ than you have in Visual Studio. In IntelliJ you can have different colors for instance fields vs. static fields vs. parameters, line comments vs. block comments (plus others). The second gotcha is that the settings for Red and Blue seem to be reversed. For example, in the Ragnarok Blue scheme the plain text background setting is 0x00261A10. I used a web site to quickly translate the hex code to it’s RGB equivalence; there are many sites that can handle the conversion. Drop ‘0x’ and the first ‘00’ and plug in ‘261A10’; the code comes back as Red:38, Green:26, Blue:16. But if you plug that into IntelliJ’s RGB color tab, it won’t be right. You have to enter it backwards as Red:16, Green:26, Blue:38. I tried a couple of different translation sites with the same results so the problem is either in Visual Studio or IntelliJ.
Mappings from the .vssettings file to IntelliJ are pretty simple (anyplace in .vssettings where the color is 0×02000000 it means the color was left at the default:)
- Comment: Java->Line comment & Java->Block comment
- Plain Text: General->Default text
- Selected Text: split between General->Selection background and General-Selection foreground
- Brace Matching (Rectangle): General->Matched brace (background)
- Identifier: Used this in a few places. Java->Instance field, Java->Local variable,Java->Method call, Java->Static field
- Number: Java->Number
- Operator: Java->Operator sign
- String: Java->String
- User types: Java->Class
- User Types(Interfaces): Java->Interface
- Line Numbers: General->Line number
- Keyword: Java->Keyword
- XML Attribute: XML->Attribute name
- XML Attribute Value: XML->Attribute value
- XML Comment: XML->Comment
- XML Name: XML->Tag name
This afternoon I posted the first preview of the 2011 CodeStock Android app on the project page at http://code.google.com/p/codestock2010 (in hindsight I probably shouldn’t have included “2010” in the project name.) So far this year’s edition has a few features:
The home page displays a special background with a countdown timer until the opening of the conference.
It can also display a running stream of postings from Twitter than either mention CodeStock or originate from the official @CodeStock Twitter account. From Menu->Options, select Enable Twitter. You’ll be asked to authenticate to Twitter and grant Aremaitch Dev Test permission to access your Twitter account (this name will change when the app is finally released to the Market.) Once this is done you’ll be able to set how often your device will download tweets, how long each tweet is displayed, and how many days of tweets to keep.
There have been many internal code changes to help minimize memory and cpu usage; feel free to take a look. And, of course, if you see something that could have been done better, don’t hesitate to let me know.
I’m planning to deepen the Twitter integration by letting you send tweets tagged with #CodeStock. I’m also planning to add session notifications and integration with the device calendar. Let me know if you have any ideas for additional things to add.
I’m a bit late in posting this but on November 6th when I spoke on Android and .NET Services at the Fairfield / Westchester County Code Camp I sat down for an interview with Peter Laudati’s Connected Show podcast. The episode is live and available for your listening pleasure here.
So it turns out that Windows Phone 7 does support multitasking and does support SQL CE. It’s just that you can’t have it because Microsoft doesn’t want you writing shitty apps that show their phone in a poor light (at least that’s the “not-quite-so-between-the-lines” take-away from today’s New York City launch event.)
Funny thing about my Android phone. It ran like crap with lousy battery life until I rooted it and removed the junk Sprint pre-loaded on it. We’re about two weeks away from GA of Windows Phone 7 and all the demos are still pre-production units. It will be interesting to see how much stuff AT&T and T-Mobile preload on these phones (that you, of course, cannot remove.)
I’ve been exploring the Windows Phone 7 SDK in preparation for a launch event in New York next week by porting the CodeStock Android application to WP7 and I’ve run into a bit of a headscratcher.
The Android app uses a context menu option to permit the user to refresh the data from the website “on-demand” so I created an ApplicationBarIconButton (named “downloadScheduleButton” surprisingly enough) for the same functionality. On first test the app crashed with a null object reference on the line in the main page’s constructor added to wire-up the click handler. The line of code looks like this:
this.downloadScheduleButton.Click += new EventHandler(downloadScheduleButton_Click);
The null reference was “downloadScheduleButton” and yes, I did put the line after the call to InitializeComponent(). The generated SilverLight code for the page included this line in InitializeComponent:
this.downloadScheduleButton = ((Microsoft.Phone.Shell.ApplicationBarIconButton)(this
but FindName was returning null. The docs for FindName included this note:
"A run-time API such as FindName is working against an object tree. These objects are loaded into the content area and the CLR runtime engine of the overall Silverlight plug-in. When part of the object tree is created from templates or run-time loaded XAML, a XAML namescope is typically not contiguous with the entirety of that object tree. The result is that there might be a named object in the object tree that a given FindName call cannot find."
The docs continue by discussing using GetTemplateChild, VisualTreeHelper, or XamlReader.Load but none of the cases seem to apply here. Further, the ApplicationBarIconButton class doesn’t expose a Name property so I can’t write my own method to loop through buttons and matching by name.
I got around it by using
((ApplicationBarIconButton)this.ApplicationBar.Buttons).Click += new
but that’s awfully fragile and will break if the order of buttons is rearranged. What am I missing here?
Had a great time this past weekend in Richmond, VA for Richmond CodeCamp X. Had a good turnout at a great venue and while my session was rather sparsely attended we had some good discussions and questions.
As promised here is the slide deck and the sample apps. The ZIP file does not include the Restlet and ksoap2-android libraries (because my web host limits upload sizes) but you can download Restlet from http://www.restlet.org. There has been a revision to the Restlet library (from v 2.0.0 to 2.0.1) but I’ve tested the sample application to make sure it works with 2.0.1. There have also been changes to the ksoap2-android library in that the dormant 2.4 fork has been taken over by Manfred Moser, who had created the original 2.5 fork. The 2.5 fork (which is the one my demo used) is gone and only the 2.4 fork is available. The 2.4 fork can be downloaded here. The Eclipse folder is meant to be the root of an Eclipse workspace so I didn’t include the .metadata folder.
Inside the folders for the two Eclipse projects there are “libs” folders that are placeholders for the Restlet and the ksoap2-android libraries; you will probably have to fix-up the classpath for both projects. The Visual Studio project is meant for Visual Studio 2010 Professional or higher.
With CodeStock behind us I thought it would be a good idea to do a little post-mortem analysis of the CodeStock Android app to see what went right and what went wrong.
What Went Right
- Scanning a QR code to link My Sessions with the web site’s Schedule Builder. I didn’t know ahead of time that the web site would generate a QR barcode to access the user’s schedule. I had started designing a layout to prompt the user to enter their website id but scanning the barcode is much more in keeping with the Android mantra of a seamless device experience. There were a few people that mentioned before and after the conference that they didn’t know you could do that with Android (having one application call another, unrelated app that returned data to your app.) Definitely cool.
- Downloading speaker photos and caching them to the SD card. Downloading the photos on a background
AsyncTask. and saving them to a directory on the SD card avoided having to download them multiple times. The trickiest part was figuring out how to avoid having the photos show in the device’s Gallery app. The solution was to add a file named “
.nomedia” to the directory where the photos are stored. The file could be zero-length; it just needed to exist. It was also a surprise how flexible the
TextViewwidget is. It can hold much more than just text by using
Editables. It’s something I want to spend more time understanding.
- Parsing speaker bio’s and session synopsis. Many of the speakers originally uploaded their bio’s and their session’s synopsis with embedded Html formatting. A couple of speakers apparently used Save as Html from Microsoft Word and just pasted the document into the web site, complete with all the Microsoft object model junk. When I started the project I fully expected to have to write all sorts of nasty code to parse out this junk. Turns out the
TextViewwidget combined with the
android.text.util.Linkifyclasses is fairly forgiving of what you feed it. The
Html.fromHtml()method will take nasty html and return something sensible for
TextViewto display while
Linkify.addLinks()will scan the contents of the
TextViewand turn recognized text into hyperlinks. It was fairly simple to add a filter that extended
Linkify.addLinks()to recognize Twitter handles and to add a handler to
Html.fromHtml()to teach it to handle html tags it didn’t natively support. For a complete picture, see the code in
DisplaySessionDetailsActivity.java, especially the
displaySessionInfo()method and the
What Went Wrong
- Image icons on the start screen suck. No other way to state it. I’m not an artist and can’t draw to save my life (I’m so jealous of people that can create nice artistic images.) That’s one of the reasons I haven’t done much with ASP web pages because I can’t come up with a layout that doesn’t look like it was done by a developer.
- Database access is fragile. The coordination of opening and closing the database was tricky to get right without the OS throwing a “Database leaked” exception and any changes to the app that involved db access would break the access. As I mentioned in my presentation you don’t have to use the “extending SQLiteOpenHelper” pattern. I’m going to try to refactor it to use some sort of singleton pattern, perhaps opening the database at app startup and closing it only when the app completely exits.
- Handling orientation changes while AsyncTasks are running is fragile. Because Android basically kills then restarts your activity when the device orientation changes creating and showing a
AsyncTask.onPreExecute()then dismissing it in
AsyncTask.onPostExecute()can cause a Window Leaked exception. What happens is the recreated
Activityknows nothing about the
AsyncTaskhas an invalid reference to a non-existent activity. I changed My Sessions to download the Schedule Builder data using an
AsyncTaskbut had the activity
ProgressDialoginstead of the
GetScheduleBuilderSessions AsyncTaskclass. The class still sets the text in the
ProgressDialogand shows and dismisses it but the dialog is owned by the activity. It seems to work fine and is much simpler than the mess in
The CodeStock data API will be staying up for at least a while so I plan to correct and refactor some of the above issues. I’m also planning to target Android 2.1 and higher so I can do some of the things I wanted to do but couldn’t because I didn’t want to leave the 1.5 and 1.6 users behind. I also have another idea that I’ll keep to myself for the moment. I’m also planning to port the application to Windows Phone 7. I do plan to blog about most of this.
Forty-nine people downloaded the app (28 of you still have it installed) and for the most part the comments were very nice. Several people come up to me during the conference to say they liked the app and used it all the time. Thank you for the kind words. If Michael wants me to I will definitely do another one for next year.
This past weekend I once again made the trip to Knoxville, TN for the CodeStock conference. This conference, run by Michael Neel, has, in only a few short years, become one of the more respected US East Coast technical conferences. Version 2010 moved to a new home (the University of Tennessee Conference Center) and added more tracks that really made it the conference with something for everyone.
I had submitted a proposal for a Beginning Android talk and was honored to have it chosen as one of the top five vote getters. Since I drive down from New Jersey and based on last year’s experience, I headed down on Wednesday instead of Thursday. I planned on using the extra day down there to tweak my session.
A few people asked me why I drive down to Tennessee from New Jersey instead of flying. I’m not afraid to fly and enjoy the experience of getting into a giant metal can in one location and, a few hours later, getting out in a completely different location. What I no longer enjoy is the process of getting to that giant metal can. I hate parking at the airport and getting raked over the coals in parking fees. I hate getting poked and prodded by security at the airport and definitely don’t like these full-body scanners nor what passes as security policies these days (I’ll spare you my political views but if you know me at all you can probably guess.) But what I detest the most is queuing in excruciatingly long lines that don’t move. It really makes me crazed just standing there waiting, doing nothing. Since I like to drive just give me a few podcasts and my satellite radio and I’m all set. I was actually surprised at the number of speakers this year that drove instead of flying.
It’s not very interesting going into a minute-by-minute rundown of my time there but I’ll just call out a few high points:
- First high point was Thursday morning. I was sitting in the open spaces area when Kevin Griffin (at least I think it was him; I may be mis-remembering) came in and asked me if I wanted to join in with the Community Megaphone podcast that was being recorded on “Speaker Horror Stories.” What most people at CodeStock didn’t realize is that this was my first time speaking at a conference and my first time speaking on Android. I’ve spoken at small user groups in the past but the last one was almost five years ago. As the podcast unfolded we went around the room introducing ourselves and relating our stories. When the microphone got to me I said I really didn’t have any horror stories because I was a “conference-speaker newb.” The other speakers in the room burst out in applause and really made me feel welcome to the speaker community. Thanks guys. It really boosted my confidence and made me glad I took the plunge. I will definitely do it again.
- Second high point was my actual talk. Being so concerned with running out of material I badly misjudged the time and had way more material than I could use. That had to be the fastest 70 minutes of my life. I don’t have the official count of people in my session but it looked like a full house and not many people left before the time was up. My thanks to those of you that came to hear me and especially the ones who gave up part of their dinner time to see the OData demo.
- Third high point was Friday night in the room the hotel set-aside for us to socialize and play guitars. My friend Wendy was playing with a Lego Mindstorm robot and the Microsoft Robotics studio and was having problems getting her program to work correctly. There were a few other people at the same table so here are four professional software developers with probably three or four decades experience combined sitting there trying to make this program work but it wouldn’t go. Then Wendy’s 16 year old son (who was with her at the conference) sits down at the laptop, removes a few components then replaces them, and the whole thing started working. Total time expended by the professionals: at least an hour with no progress. Total time expended by the 16 year old: probably about 2 minutes with total success. Guess we all need to go find new careers. (As a side note it was quite a treat to see a mother and her 16 year old son pair programming. That’s a combination you don’t see every day.)
- Final high point was Saturday night. I was planning on just taking a pizza back to my room, watching a movie, and calling it an early night cause I knew I had a long drive home Sunday. But I went down to the bar anyway and found the DevExpress gang; Gary Short (@garyshort), Plip Winstanley (@plip; who isn’t actually part of DevExpress) and Rachel Hawley (@rachelhawley; one of the famous Rachii) along with Seth Juarez (@sethjuarez; who did a double session on machine learning that I’m really sorry I missed.) We spent the next few hours discussing everything from software development to the geo-political state of the world. If you ever want a really eye-opening experience speak to people from another country (Gary, Plip, and Rachel are from the UK) about their views on your country. Definitely food-for thought. Conversation continued on the patio with Miguel Castro (@miguelcastro67) and John Petersen (@johnvpetersen.) I now know a lot more about 18 and 25 year old Scotch whiskey than I did before.
Next year’s CodeStock conference isn’t scheduled yet but will probably be sometime near the middle to end of June. If you’re on the East Coast (or even if you’re not) you really need to consider adding this one to your conference schedule. I’ll be getting the slides and code from my talk to Michael within the next day or two so be sure to watch your email for his blast. I’ll also post them here and tweet/blog when they’re up.
Just a quick post that the next part is going to be delayed. The baseball OData feed is down and I have no idea when it will be back (I don’t have any control over it.) So I’ll have to regroup and figure out what to do in case it doesn’t come back.