Monday, July 26, 2010
I spent the rest of that night ferreting out bugs that didn't exist in my tests. God bless patient testers (I'm looking at you, Patrick Kettner).
Little did I realise, however, that this would be a global entrance into the Market. I understood that people all over the world could use my application... I just didn't think they would. In the weeks since, I have been shown how wrong I was.
First, a disclaimer. All these numbers are coming off the project page. This is based on the assumption that people going to the project page are people who are actually using the project. In the next release, I'll be tracking statistics for the actual application, so my numbers will be much more specific and accurate.
Since its release, android2cloud has seen visits from over 700 people, in 313 cities, across 42 countries. The country driving the most traffic is Japan. It has served over 1,000 links, and has 209 users. (Those last two came right from the database, so I know they're accurate.)
A large part of this popularity can be accounted for, I'm sure, by the coverage the application has received. Juggly.cn, a Chinese (I believe) blog, covered the app twice, here and here. Moongift.jp, a Japanese (I believe) blog, covered the app here. After these three articles were written, the visits to the projects page and the app usage both skyrocketed. As I write this, the server is serving 6 requests every second, and has served 250 thousand requests in the last 12 hours. As I upgrade the software and App Engine gets its Channels API, I expect the requests to plummet. Still, App Engine has handled this huge amount of traffic without even blinking. The free quotas absolutely covered all the traffic, and I've not seen any unscheduled downtime.
All in all, android2cloud was a huge success. I've been contacted twice about translation and localisation efforts, and the wonderful people at Yensid have contacted me about writing Android apps. I've brainstormed two new applications, and will be launching them in the future. An update is planned for android2cloud, and is mostly completed. I expect to release it in the next few days.
Thanks, everyone, for your support. Especially the people that are donating; you really are too generous. I'm doing my best to repay you for your kindness, and hope you like the features that are coming. If you have ideas I haven't implemented, please contact me on the Google group, or file an issue on the issue tracker. I love hearing from users; you always have better ideas than I do.
Tuesday, July 20, 2010
I do not, however, intend to rest on my haunches. There have been a couple of suggestions, and there are a few features I'd like to see included, as well. A few of these are taking priority right now:
- "Silent Sending": this was a feature I hadn't thought of, but one of the commenters in the App Store requested it. Essentially, it asks that users can elect to skip the screen entirely, and just push their link to the cloud from the share intent, in the background. This requires a major restructuring of the code, but I'm hoping to include it in the next update.
- Settings for the Chrome Extension: this is an embarrassing oversight on my part; I thought I had included a settings page in the Chrome Extension before release that allowed people to select their server and change the account they were using to authenticate. Clearly, I was mistaken. I am working to rectify this, but there is a bug in Chromium's OAuth code that is blocking this. As soon as that bug is fixed, I'll be releasing this to the general public.
- Login Failure Detection: right now, the error handling for logins from the Chrome Extension is a bit... crude. It does nothing; doesn't alert you, doesn't log you out, nothing. If, somehow, your OAuth token or secret gets corrupted, changed, or stored incorrectly, Chrome will happily just keep pinging the server, and will do nothing when the server returns an error. I have a system to handle this largely in place, but it's being blocked by the same bug that Settings is being blocked by. As soon as that bug is fixed, I'll be rolling out that update, as these two features should have been included from the get-go.
- Allow moving the app to SD storage: This one should be a relatively simple fix. Someone has requested that they be able to store the app on their SD card. I thought about including that, but didn't think it was worth it, as the app is so small. It will, however, allow people to move the app between phones simply by moving their SD card, and it has been requested, so I'll enable it for the next release.
Saturday, July 17, 2010
I ran through several different iterations of the account support in android2cloud before I finally managed to make this work. Save yourself the trouble, Focus on one thing at a time. This project can be broken down into component parts, and those are much easier to tackle. Half the time, I wasn't entirely sure whether Android, Signpost (the OAuth library for Android I was using), or App Engine's OAuth implementation was at the root of my problems, and debugging was frustrating when I tried doing it all at once. Save yourself that headache. Build in Java first. The first thing I did was build a working Signpost client that ran from the command line. I abstracted every single step of the OAuth protocol into its own method, and tied them all together in main(). When I got that authenticating against App Engine, I knew any subsequent OAuth issues were solely due to my handling of the protocol in Android.
- Signpost on Android doesn't work with the DefaultOAuth* classes. Use CommonsHttpOAuth* instead.
- You need to make sure you add a header to your request, or App Engine will complain. Here it is:
- Your consumer key and secret are both "anonymous"
Make Mine Mobile
Once you have the working Java implementation, it's time to port it over into Android. This is tricky, because you need to pass a lot of information between Activities, and sometimes you don't even control the activities, so managing your information gets to be a tricky business. Intent.putExtra will become your best friend, and a solid understanding of startActivityForResult and Intent.getIntent will save you a headache or four.
- Figure out how you're storing information ahead of time. It will save you trouble. Remember you need to store, at the very least, their token and secret.
- Store your consumer and provider in fields. It's much easier than instantiating new ones every method.
- I shouldn't even need to say this, but store your host, URLs, consumer key, consumer secret, and any other constants as... well... constants.
- Add "btmpl=mobile" to your authorize URL to get a mobile version of the authorization page.
Another interesting note is the debate between WebViews and the browser. I chose to open a WebView for users to authorize the application with. As Abraham pointed out, that's asking a user to trust my application not to harvest their details through that WebView. He suggests I use an Intent and protocol filter to process the callback. I actually experimented with that method, and found it not to my liking, as it made the back button's functionality weird, and sent unexpected results to the application, at times. After his suggestion, though, I'm back to tinkering with it. If I can make it consistent and user friendly.
For those interested in how I handled the callback, I actually set a callback URL on the host. When the WebView loads a page, it checks the URL. If the URL matches the callback, it extracts the returned parameters. Otherwise, it just loads the page up. I found this to be the most immersive, user-friendly experience, so that's what I went with. I'll write again if I switch to the protocol method.
And, of course, all of my code for my OAuth implementation is in the project's source on Google Code. I'd be flattered if anyone actually used it, so hack it apart, take a look at how I did it, or anything else you want to do that will save you some time. And if you have suggestions or find bugs, go ahead and file an issue. I'll work on it.
Monday, July 12, 2010
I hit the big green "Publish" button last night; today saw its first upgrade, to version 0.1b (a few usability tweaks and support for Android 1.5). You can find the app in the Market by searching for "android2cloud"—you'll notice there's a Donation app, as well, if you feel like tossing a buck my way. The applications are 100% identical, however.
The Chrome Extension is also live. You can download it here.
I set up a default app engine server at http://android2cloud.appspot.com. You're not going to see much there through the web interface.
Of course, all of this can be downloaded, inspected, and viewed at http://code.google.com/p/android2cloud. The entire project is open-sourced, and I'm releasing it there. By all means, open issues, leave feedback, and (if you can) contribute code to the project! I built this as decoupled as possible and open-sourced it for a reason. I want it to grow beyond me.
We also have a discussion group at http://groups.google.com/group/android2cloud. Stop by and say hi!
I learned a lot from developing this application. I used three different programming languages, four different frameworks, and three technologies that were entirely new to me. It was a challenge (more on that in a minute) but it was absolutely worth it.
If you remember correctly, the last time I posted about this, I was at a roadblock, having trouble with OAuth and Google App Engine. I'll be drafting a post in the next few days about how I debugged the issue and got around it, and will be sure to include a step-by-step tutorial on how to implement OAuth with Google App Engine from Android in the future, along with some common pitfalls and mistakes.
Go on, give it a try. Let me know what you think.