Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Monday, June 20, 2011

Some Notes on Implementing In-App Billing on Android

About a year ago, I implemented in-app payments for iOS, and it was painful. Technically, it wasn't too hard but there were a number of hoops to jump though to get everything working. Lack of clear documentation and undocumented error responses seemed to be the primary problem - I think a hold up with verifying tax information on the developer account resulted in strange, undocumented failure codes in my case. There were several dozen blog posts complaining about many such "magic" issues back then. It was almost comical, to be honest.

This last weekend, I decided to add in-app billing to an app that's already shipping for Android, and I ran into a couple of hiccups that I think are worth documenting here to save others some time/pain. Overall, I think the Android folks learnt from some of the pitfalls that early developers hit with in-app payments on iOS and worked to fix those. The documentation is a lot clearer and precise compared to where iOS was a year ago. Android Market also has a nifty static test/response facility which makes it easy to test code without worrying about external influences. iOS was desperately lacking something of this sort (not sure if it's better now) - I even wrote a dummy implementation of the iOS in-app payment API and the different response conditions to let me test my code in an emulator, which was really helpful. I'm glad Android got this right (still no testing in an emulator though, which is a bummer because of the inability to test with different Android OS versions).

At a high level, the in-app billing protocol on Android is extremely chatty (see the diagrams on this page). It seems particularly so when compared to PayPal's rival offering. PayPal's in-app billing module handles payment using startActivityForResult and onActivityResult methods which can be used for communicating between child/parent activities. This is very similar to how Facebook's Android SDK handles single sign on. That model is extremely simple to understand and implement for developers - you could probably have it coded up and tested faster than you can finish reading this blog post. I think part of this chattiness is to ensure a higher level of security and also to handle managed purchases, which are both likely harder to do using PayPal's approach. I assume they had good reason to make it as chatty as it is now, but my gut says that Google loses out on a lot of developers because of this apparent complexity. Having said that, the sample application Google provides does a really good job of illustrating the various communications that need to occur, so studying that code makes the chattiness easier to understand (for some reason, code registers more easily in my brain than verbose documentation - good code and good documentation together are very rare, and Android seems to have gotten this right - kudos!)

One of the biggest red flags with using Android's in-app billing, however, is the development teams non-responsiveness to critical bugs. This issue, marked critical and accepted, talks about transactions failing 4-6% of the time, and has been active for over two months without an owner being assigned. An equally disturbing issue with unacceptably long latency when handling authorization has been open for almost two months without any comment from Google or even an owner being assigned. In fact, browsing the issues list certainly doesn't inspire confidence in the platform. It would be a big mistake by Google to not take these issues seriously. In my case, I'm certainly debating the merit of jumping into this as an early adopter.

Some other notes about implementing in-app billing on Android:
  • It sounds obvious in hindsight, but you need to make sure that your application is signed with the release key before testing in-app billing, even the static response stuff. Developer's aren't used to doing this while debugging, so it's worth calling out in the documentation.
  • If you want valid signatures for the JSON responses as suggested by the table here, the "debuggable" attribute in the app manifest should be set to false, even if you're using a release-key-signed APK and static responses. I was a little annoyed by this un-documented restriction because it basically meant that I had to resort to using logging as the only real means of debugging my code. If there is indeed some way to debug this using a debugger (and yet receive valid signatures), it’s definitely not obvious to me. Again, not a terribly big deal once you realize that this attribute actually seems to affect signatures, but that isn't documented anywhere.
  • If you're using a server to validate signatures (as you should), be aware that the public key you obtain from the Android Market profile page is a base-64 encoded string. You will almost certainly need to convert it to PEM/DER format or use the x509 certificate for it to be usable with most server openssl implementations. For instance, this command can be used to convert the base-64 encoded key into a key usable by PHP:
    openssl enc -base64 -d -in publickey.base64 -A | openssl rsa -inform DER -pubin > publickey.pem
    Also, if you're using the PHP function openssl_verify, remember that $signature needs to be the binary signature, not the base-64 encoded signature string that the Android Market app sends (I found out the long way).
  • Unavailability of subscriptions/auto-billing is a big gap in the offering currently, but I assume support for it is coming soon, since iOS already supports it.
  • I hit an issue when testing payments using carrier billing, where accepting the carrier ToS basically causes the transaction to get lost somewhere between the carrier and Android Market. I logged this bug to track the issue.
Well, I hope that the web-search spiders do their job and this post helps others out there looking at implementing in-app billing on Android. And making Google get a move on those bugs.

Wednesday, September 30, 2009

So, how was your date?

A funny exchange at work today...

I designed this piece of UI putting together all my newly-acquired Javascript and Paint.NET (a free Photoshop-like tool) skills, and it looked pretty fancy for what I thought I was going to end up with. After playing with it for a bit my co-worker responded: "Thanks for putting that together Viraj - I really like the concept. I can't wait to see what a designer can do with it".

Lol... this sounds a lot like the "She's got a great personality..." line of the dating scene.

Like I said previously, UI design is so much harder than I thought it was!

Friday, September 18, 2009

Fix for slow Firefox/Chrome connects to localhost

While doing some recent testing I noticed that Chrome(v3) and Firefox(v3.5) are both very slow to connect to http://localhost on Windows 7 - both take ~1 second just to connect.

I initially suspected something was wrong with the webserver on localhost, but once I validated that wasn't it, I found some blog posts about others who had noticed this in Vista and XP. Essentially, disabling ipv6 takes care of the slowness.

However, to fix the issue, have the client use http://127.0.0.1 instead of http://localhost - it bypasses ipv6 without you needing to mess with browser configuration.

Saturday, August 29, 2009

Know What you Inherit

I ran into a couple of bugs recently that took longer than they should have to fix. Like all bugs, it seems obvious now that I know what was wrong but I think I spent a total of 5-6 hours investigating and fixing this across multiple platforms (hey, this is what makes developing software fun!). Here's hoping that those fancy search engines will help someone else find this post and save them time incase they have a similar problem.

I was working on some code that launched another process. This is a fairly mundane task. Interestingly though, the process launched went on to kill its parent and re-launch another copy of the parent. So, process A is running and launches process B, which then kills A and launches A'. Sounds kinda simple, right?

Well, everything seemed to work until I noticed that some resources needed by A' weren't available (ports/files). That seemed odd, given that A had been using those same resources successfully, and those should now be available since A was gone. The title of the post gives it away, but the problem is that a fork causes child processes to inherit the file descriptors/handles of the parent, so the files/ports opened by A were inherited by B and subsequently by A'. This meant that they weren't really cleaned up by the OS when A exited. Hence A' could not re-open those resources (some were locked for exclusive use).

The really interesting aspect of this bug was how it manifest itself on different OSes and the different fixes.

On Windows, TCPView showed the ports in use by a "<non-existent>" process. The PID of this process was that of A, which was already gone by now and didn't show up in the list of running processes.

After some analytical debugging, I guessed that the handles were being inherited by the children resulting in these strange 'orphaned' ports. The solution on Windows was to use the CreateProcess API with the 'bInheritHandles' flag to FALSE. Problem solved. By the way, the not existent process IDs attached to those ports seem to imply that the OS tracks ownership by processID, and hence cannot validate that the new owner of these is the child process now that the parent is dead - the child obviously has a different process ID. This might not be really how it's done, but seems logical.

The Mac was much more interesting. The manifestation of the problem was simply unavailability of the resources. There isn't an equivalent of the bInheritHandles flag for the fork command on UNIX. To cut to the chase, the solution was to fork the process, close all open file descriptors that it inherits and then call exec.

Now, the Mac guys have added a nifty 'open' command to the system which helps launch processes as a child of the launchd process, which doesn't inherit the callers file descriptors (it's parent is the launchd process). However, this open command has a couple of pretty severe limitations. It can only open app bundles, not native binaries. And you can't pass in command line arguments to the application you open. FAIL on both counts! Mac purists will claim that command line arguments aren't the 'right thing' on the Mac, and that Apple Events should be used instead. That's BS, really. For anyone writing platform independent C++ code, it's just not practical. People don't realize that not every app on the Mac is a Cocoa/Carbon app. Anyways, so on OS X I needed to be a little creative and have A launch B, but before doing anything useful in B enumerate all open file descriptors and close them (readdir() /dev/fd on FreeBSD and Darwin enumerates all open file descriptors). Oh and by the way, you might not want to close FDs 0, 1 and 2 - they're stdin, stdout and stderr respectively. This post on StackOverflow has some good related information incase you're curious.

Friday, August 7, 2009

To Every Web/UI Developer I've Scoffed At - Apologies!

I am/was a cocky programmer. Having only worked on system and application level programming thus far, I really didn't appreciate how hard building a good, usable website or application is. I knew that an application or a system is only as good as how usable it is, but I really considered usability to be a 'simple' problem and by inference I assumed that writing the code behind what you see on a website or an application is also 'simple'. As my career matured I suspected I might be wrong, and now I know I was!

Over the last few weeks, I've been messing quite a bit with Html and CSS to make stuff look non-ugly and Javascript/Ajax to make stuff feel non-sluggish. And the combination of these together to make non-ugly things appear non-sluggish. Of course, this also means dealing with everything that goes on in the middle/backend to support non-sluggish, non-ugly things. Oh, and once you have something that's not ugly and not sluggish, you have to worry about the bad guys. Cross-site Scripting, Cross-site Request Forgery, cookie theft and poisoning, etc are things I didn't think much about previously. What cans of worm those are... !

And then a couple of months ago I spent some time making an mac application non-ugly and non-sluggish. Same deal, pretty much.

Working on these new technologies sure feels like being a kid in a candy store, but I have to confess my new found respect for good UI/Web developers (and I am not one, by a long shot). I may have snickered behind your backs previously, but it sure won't happen again!

Tuesday, June 30, 2009

New Technology (for me) Roundup

Over the last almost 2 months, I've messed with several new technologies - some extensively, some briefly - that I hadn't used previously. This post is primarily a journal entry documenting my impressions of and experience with these, so far:
  • PHP - Exposure : Medium
    I think I really like PHP. It seems like it's a good blend of a traditional programming language and a scripting language. I like that it allows for well designed software with OO constructs being first class citizens. I also like the flexibility that the scripting language aspect of PHP provides. I wish there were some kind of PHP compiler which helped catch silly typo-like issues before runtime, but I guess that's the price you pay for having the conveniences of PHP. I also think I would like having a good PHP debugger - currently I use code review and tracing as debugging aids. They've worked so far but I hope I never have to chase down something really nasty or subtle using these techniques.

  • Objective-C/Carbon/Cocoa - Exposure: Medium High
    I previously wrote about my experience with programming for the Mac. For someone familiar with C and working with a runtime framework, this shouldn't be hard to grasp. I think I'm pretty comfortable with these technologies, but in many ways these are forced down your throat if you want to write software that runs on a Mac, and looks half decent. I dove deep into a few things related to these technologies (debugging crashes, file system events, application run loops, network support, deployment) and it was kinda fun and fulfilling to accomplish complex tasks with these technologies.

  • Bash Scripting - Exposure: Medium Low
    To be productive in a Linux development environment, mastery of scripting is key. I know just enough to get me by, and I'm sure there's so much more I could do to improve. The rule of three seems to work well... if you do the same task three times, script it. And most times, you'll discover it's already been scripted by someone else or simpler still, exists as a built in set of commands. This seems like one of those endless holes of expertise that never ends. My goal is to deal with this as needed instead of being overly enthusiastic about becoming a crazy script monkey.

  • Javascript - Exposure: Low
    I'm actually not too bummed about not having had to mess with more Javascript. I know people who just do the craziest things with Javascript and AJAX, but I'm not creative enough (or perhaps not motivated enough) to do anything more than the minimal. Unfortunately, a minimal website only works if you're Google or Craigslist. I haven't messed with Javascript for more than just a few hours, so I don't really have any strong opinions except that for someone who isn't familiar with scripting it takes some getting used to. Something like Script# might be an ideal transitionary tool though (I haven't played with it at all).

  • MySQL - Exposure: Medium Low
    MySQL seems really slick. It feels great for simple database functionality (haven't really done anything too fancy with it) and supports some SQL syntax that comes in handy versus Microsoft SQL Server (insert ... on duplicate key update, create table if not exists, etc). PHP support for MySQL seems like a great integration win for both technologies. I haven't really dealt too much with administration and performance issues though, two areas which are super important to a great database solution, so I can't comment on those.

  • Python - Exposure: Low
    I wrote a couple of python scripts to get some pretty powerful tasks done. I like that it has a bunch of libraries that enable you to write pretty fancy applications if you're so inclined (I'm not, and likely never will be). Like most scripting languages I'm amazed at how much can be accomplished in a few lines of code. Generally though, I don't like too much magic being done for me when I don't really understand what's happening and my experience with Python certainly made it seem very magical. Which is great for getting small tasks done, I guess.

  • Vim - Exposure: Medium High
    This is a big once - even after almost two months of using this daily, I'm not nearly as comfortable with it as I was with the Visual Studio IDE, which makes me feel like I'm not being as productive as I can be. I think I learn one or two new tricks every day that make me wonder if there's anything Vim can't do. It's another one of those 'rabbit hole' technologies where experts can tune it to crazy levels. My approach is more along the lines of 'fix it when it annoys you' which seems to be working (slower than I would like, I admit). It certainly has the potentially to make me super productive once I get better with it, and that's making me stick with it.

  • Others - Exposure: Low to High
    Technologies that aren't really 'new' for me but I was out of touch with for the last few years and have reconneced with recently:
    - C
    - Linux
    - Win32
    - Batch file scripting
    - Makefiles
    - gdb
So yea, as you might be able to tell, the last couple months have been insanely fun. I feel like an intern again (in more than one way ;-) )!