Managing Complex Mobile Transaction – An Android Implementation

12 11 2011

A colleague of mine, Jack Cox, wrote an article recently about managing complex mobile transactions. The article is written with an iOS slant but I found it very interesting and wondered if the paradigm could be implemented in Android and whether it could be effective. After sitting down and doing some brain storming, I realized the pattern lent itself very well to Android.

Let’s review some of the main components of Jack’s pattern:

  • Controllers — Typically view controllers, responsible for requesting data, processing results and presenting them to the user.
  • Commands — Encapsulates everything needed to make a service call including the data for the call itself.
  • Exception listeners — Responsible for taking action on any non-expected exception thrown from the service tier call.
  • Command Queue — Responsible for managing network requests. Controllers will place requests onto the Command Queue and listen for responses. Exception listeners will also listen for unexpected responses and deal with them appropriately.

This paradigm really lends itself well to Android’s own Command Dispatch pattern implemented by the use of Intents, Services, and Broadcast Receivers.

Overview

An Android IntentService will be used as a RESTful service delegate, hiding communication details from components that need to communicate with back end services. The IntentService is also the Android representative of the iOS NSCommandQueue (command queue) in this pattern. Intents will be used as the Command object in this interaction and meshes well with their current use within the Android operating system. BroadcastReceivers will play the part of exception listeners and will also be leveraged by Activities who are the Android representative of an iOS View Controller. The implementation details do change slightly due to the differences in operating systems and will be covered in subsequent sections. Intent Filters based off of data in the Command Intent, will allow for targeted broadcast notifications of RESTful service results (or failures). We’ll follow a convention over configuration pattern for targeting specific broadcast receivers with results from service calls.

Operation.Request and Operation.Response (Data)

Marshallable and unmarshallable data objects representing an operation request and response will need to be created for each RESTful operation. These data objects will also need to be Parcelable so the operating system can use interprocess communication (IPC) if necessary. These data objects will extend from 2 abstract classes, OperationRequest and OperationResponse, that will serve as marker interfaces, have common attributes across all services, as well as to enforce certain contractual needs required by the Rest Delegate Service.

Intents (Commands)

Intents are used as the Command objects and will contain all the information necessary to make the network call, the results of that network call, and routing information based off the Intent metadata The action and category metadata for the Intent is different throughout the lifecycle and is dependent on where in that chain as to what the value is.

Rest Delegate Service Intents – Are explicit intents and will contain the following extras:

  • “rds.service_request” – The OperationRequest and should contain everything necessary for the Rest Delegate Service to make a RESTful call to the service tier and formulate a response that can be broadcast and understood by all Broadcast Receivers.

Broadcast Receiver Intents – Are implicit intents and will identify their consumers by a combination of the Intent’s action and category metadata. The action will be a static string, “me.ericmiles.mobiletrans.ACTION_REST_RESULT”. The category will be one of three things: the fully qualified name of the response type, ie “me.ericmiles.mobiletrans.ops.LoginOperation.Response” , the fully qualified name of the exception caught during service communication, ie “org.springframework.web.client.RestClientException”, or the default exception category if no Broadcast Receivers would react to a caught exception “me.ericmiles.mobiletrans.UNKNOWN_EXCEPTION”. The category is the key component to allow broadcast receivers to filter out intents they do not care about. This will be discussed in more detail in the Intent Filter section. Broadcast Receiver Intents can have the following extras:

  • “rds.service_request” – The OperationRequest that was used to make this service call. It is sent in the Result intent in case an exception Broadcast Receiver wishes to try the request again.
  • “rds.service_response” – The OperationResponse received from the RESTful call if one is returned.
  • “rds.http_response_code” – The HTTP response code if one is returned from the RESTful call. May be used in processing by broadcast receivers.
  • “rds.exception” – The exception if one was caught.

Broadcast Receivers and Intent Filters (Listeners)

Broadcast Receivers will be used as listeners for RESTful service operation responses. These Broadcast Receivers could be registered programmatically within an Activity or can be registered statically via the Android manifest. Programmatically registered Broadcast Receivers will generally be for a specific operation for an Activity. Statically registered Broadcast Receivers will generally function as exception listeners, handling unexpected errors that transpire during RESTful communication. Broadcast Receivers extend from the Android BroacastReceiver class.

Intent filters are used throughout the Android ecosystem by Activities, Services, and Broadcast Receivers to filter Intents they are only interested in. In our communication pattern, we want to encapsulate logic to handle specific responses in their own broadcast receivers, be it regular RESTful responses or exception handlers.

Permissions

Normally broadcasts are sent across the entire device, allowing any components that has registered for an Intent to receive it. As a protective measure, to prohibit outside applications registering for our RESTful response broadcasts, we will require an Android permission to be used for all recipients of the implicit Intents used for operation responses. This permission will also be designated with the “signature” protection level, meaning that only applications that have identified using this permission and having been signed with the same certificate as the defining application can receive this intent. This will rule out any other application from being able to receive these Intents unless they somehow manage to get ahold of the signing certificate (keep those secure!!!)

Rest Delegate Service (Command Processor)

The Rest Delegate Service is responsible for RESTful communication aspect of the communication pattern. The Rest Delegate Service is an Androind IntentService; it is a special Android service that runs on an OS managed thread separate from the main UI thread. This will allow the service to handle network communication requests without blocking the user’s interaction with the UI. The Rest Delegate Service will leverage the Spring Android framework for RESTful service communication and will leverage the Gson library for marshaling and unmarshalling JSON data under the covers.

When a response is from the RestTemplate, the RestDelegateService will package up the OperationResponse, the original OperationRequest, and the HTTP response code into an implicit Intent, and fire a broadcast. This broadcast will allow any interested parties to listen for the response as there may be more than one. For example, upon successful login, not only with the MainActivity that originally fired the Command be interested, so will the Session Manager as it needs all the session information returned from the Authentication REST service. The category for the Intent will also used the fully qualified name of the OperationResponse so appropriate Intent Filters can be applied by the operating system.

If an exception is caught, there will be no OperationResponse nor will there be an HTTP response code. Instead of placing those items into the Intent, the fully qualified name of the Exception caught will be used as the category. This will allow specific Broadcast Receivers to act as exception handlers for pre-defined errors. A default, catch all will be used in case there is no match.

Activities (View Controllers)

An Activity is the controller in the communication pattern outlined in Jack’s blog entry. It is responsible for managing user interactions and what transpires during those interactions. In the Android implementation of the pattern, Activities that have RESTful service interaction will be responsible for firing off Service Intents for the Rest Service Delegate and handling those responses by managing a Broadcast Receiver that is programmatically registered for those responses with appropriate Intent Filters.

Conclusion

I think this pattern lends itself really well in the Android environment as you can see by the attached sample project. Interaction with the user gets a little tricky with the Exception listeners, particularly if you want to interact via Dialog boxes, however a there are numerous ways to skin a cat and it can be done. Check out the linked Github project and let me know your thoughts on the implementation.

Notes

I’ve included Mockey as my stubbed out service tier; it’s a pretty configurable, lightweight utility to create stubs for your service tier. If you care to use it, once started you’ll need to update the rest_endpoints.xml resource file with the appropriate IP address Mockey is running on, so your deployed application can interact with the service. Also, I’m unsure why Mockey doesn’t persist some of the configurations, but you’ll need to do the following:

  1. For the AuthenticationService’s Default scenario, also make it the “Universal Scenario Error Response”.

GitHub Project





Redfishville Shootout 10-5-2011

9 10 2011

Redfishville 2011, 4 days of fishing in Mt. Pleasant, SC with Justin targeting the awesome fighting Redfish on the flats of Copahee Sound and around the oyster beds of the Wando River. I’ve had this date circled on my calendar for quite some time. I left from Richmond on Wednesday 10-5 around 6am and got to Mt. Pleasant at 12:45pm-ish. I quickly dropped a few things off and Justin and I headed to Copahee for a few hours of fishing. We got on the water, headed for the island at the creek mouth to catch bait. After we caught bait, paddled out to the sound to hit Reds as they entered the grass. High tide was at 4:07pm this day and we had baits in the water by 2pm. Fished the grass line without a lot of success using cut mullet on a carolina rig or a live mullet under a float. Justin boated at least one nice fish at 28″+ off the grass line.

Somewhere between 3pm and 3:30pm we entered a flat and immediately saw tails. Justin headed one way and I headed another. I see one Red pushing through some pretty skinny water. I toss a paddletail swimbait in electric chicken all around the Red and get no action. BTW, flats fishing will REALLY highlight how weak your casting is. You need to hit very small 6 to 12 inch windows, which I’m not all that great at. Anyways, after casting at this Red 6 or 7 times, I get a bit impatient. Throw the swimbait just beyond him and bring the bait back into it…it bumps it and the Red spooks and swims off. Drats. I look further up the flat and see ANOTHER tailing Red. I figure the last Red didn’t like my swimbait so I switched over to a 3″ Gulp Shrimp in New Penny (it wasn’t the bait, it was my placement I later came to the conclusion). I make 3 or 4 casts to this Red and finally get a decent cast. The fish hits and it’s on! A fun couple of minutes and I land my first flats Red, an upper slot sized (don’t remember the exact size, somewhere between 22″ and 24″).

I release the fish and then proceed to catch the next 2 tailers I see, all were between 22″ and 24″. So now I’m 3 of 4 I’ve casted to and feeling pretty good. I start to make my way over to Justin and see a few more tailers. I make casts to a few and either get a spook or just no interest. I get over to Justin and at this point I’m 3 of 6 for tailers. I watched Justin hook into a decent size red only to have his leader snap after a few seconds of fight. I tell Justin I’ve caught 3 of 6 and he’s in disbelief. We both spot a LARGE tail coming out of the water on the flat in some deeper water. Luckily for me, Justin had to retie so I start making casts. I cast 5 or 6 times before the tail disappears, but it wasn’t spooked. I hold still waiting for it to reappear. After 5 more minutes the tail reappears between Justin and I. He gives me the green light to cast. On my 2nd cast I get a strike and I set the hook. Line starts peeling off back out into the grass….Hold on there fella!!! After a nice 5 minute fight, I land a nice 26 3/4″ Red.

DSCF0764-2011-10-9-22-47.png

The water starts exiting the flat and the bite slows, so we call it an evening at 5pm-ish. I have 4 Reds on maybe 10 casted at, I think Justin finished with 2 caught but he had the biggest of the day at 28″+. Between the 2 of us we saw probably 20 or so tailers…a GREAT day on the flats.

Thursday is our full “scout day” where we planned to fish both tides in Copahee so we’d have an idea of how we want to fish on the day of the tourney. We get out at 8:30am-ish and hit the water (and a bit hungover). Justin and I always have a good time when we hang out, the night before was no exception.

Dragging a bit, we catch bait and head to the Sound. Low tide is at 10:09am and high tide is at 5:02pm. My Ride is already dragging bottom on a few spots where the water is pretty skinny. We head out to some oyster mounds and start soaking baits. I’m using a live mullet under a float and cut mullet on a carolina rig. We see no action in the deeper water at low tide, so head in to the skinnier water and that’s when the action picked up (for Justin at least). I paddle up on and spook quite a few fish, but don’t hook into anything. Justin catches a few fish in the skinnier water before we head to the grass line once the water starts coming in. BTW, that live mullet lasted for 2 hours under that float until I accidentally raked it across some oyster beds and killed it.

I throw a cut mullet to the grass line and wait…I didn’t have to wait long. I get a bite, I tighten up the line and the fight is on. The Red makes several 10 to 20 yard runs and I finally wear it out after 5 minutes or so. This Red was 28 3/4″ pinched. WOW, nice Red. I release it and throw my cut bait back into the water in almost the same spot. After a short 5 minutes, I get another strike and reel down. The rod doubles over and line immediately starts peeling off at an incredible rate back out into the Sound. Line is pulled off for a good 20 or 30 seconds, I’m guessing well over 100 yards of braid. The wind has picked up quite a bit so I’m hesitant to pull my stake out pole, but I’m not getting this monster back in just sitting here. I pull the pole and the wind immediately starts taking me in the opposite direction of the fish. I manage a few one handed paddles in the direction of the line but my line is all over/through an oyster bar and the line snaps. Given that I just caught a 28 3/4″ Red and he was only able to get off short 10 and 20 yard runs where my drag was set, I’m fairly certain this was at least a 30″ Red…maybe a lot more. We’ll never know…dejected, I retie another Carolina rig and throw my line back out. I catch another 28 1/2″ Red before we hit the flats. We fish a different flat today and we don’t see a single Red. We get off the flat about an hour after high tide and head home. Justin wins the fish count today, finishing with 5 Reds but I win for the biggest at 28 3/4″.

Day 3 is Friday and we decide to fish the Wando due to the fairly strong 15 to 25mph north east winds…hoping for some relief from it. (we didn’t get it). Ran into Carter, a guide for Kayak Fish SC, at the Paradise Island launch he was chartering that day. Spoke for a few mins and watched him catch some bait before we launched. The wind was brutal and just made paddling and fishing pretty difficult. Justin and I were unable to land any bait at the launch so we were hoping to get some while out on the water.

3 hours later, no bait, no fish, and we had had enough of the fighting of the wind with no action. We pack up and head to the 41 bridge to go for bull Reds hoping to get some relief from the geography change and the change in tide. Catch some bait at the launch and head over to the hole. Cast our lines out and have them soaking for a bit when a yellow lab shows up on the bank. He seems excited to see us. He immediately jumps down in the water and starts getting in Justin’s way, swimming over/around/through Justin’s line. Justin reels up and attempts to paddle out into deeper water near me. The dog follows. The dog now swims over to me and is getting in my way. This goes on for close to an HOUR; him swimming switching off between Justin and my kayak, getting in the way. An hour of wasted fishing trying to get away from this dog who is ruining any chance we have at fishing. I can’t believe this dog was swimming in swift current, with a strong wind, for nearly an hour.

We think the dog will leave us alone if we head across the river and fish some docks; it does. Justin proceeds to catch 3 Reds underneath one dock and I go 0-fer. We call it a day and head in. I was skunked this day so I was pretty down but tomorrow will be a different day.

We knew we were going to miss the Captain’s meeting for the tourney the Friday night so we planned on doing the meetup at 6am at on Saturday morning. Overnight, one of Justin’s kids got sick and caused him to miss the alarm. I’m a heavy sleeper and didn’t wake up either so we don’t make it out of bed until 7:30am pretty certain we’re not going to catch anyone at the launch (we didn’t). We catch some bait at the island and head out, hoping to run into Ken or Tommy out on the water. The wind was insane, 25mph easily and constant. It made paddling very difficult. We saw a lot of other kayakers but didn’t attempt to weave in and out due to the wind. We just let it blow us down the grass line until we could find space to wedge up on the grass.

We fished the grass line and then hit the skinny water out around the oyster bars again through low tide. I caught 4 stingrays but didn’t manage a single Red. Justin’s having a pretty good day, landing several Reds. I finally get into a rather large one on the grass line only to have it come unbuttoned boat side after 3 or 4 minutes of fighting. I got another from he same spot about 5 minutes later but the leader snapped in half after a minute or two.

Since we were officially not in the tournament and I now had 1.5 days of fish skunk on my boat, we decided to skip the “weigh-in” and try to fish the same flat we had success on the other day. The wind picked up and became even worse (if that’s possible). There were now white caps in Copahee. Given how bad the wind was and how difficult fishing the flat would be with it, we make an executive decision to skip fishing and wait for enough water to enter the grass so we can drag our kayaks back and call it a day. Another skunk for me but Justin ends the day at 6 total. There are a couple of funny personal stories of us trying to get back to launch by dragging across the flat, diving through pluff mud, falling into a creek, etc, but I’ll spare those details.

I did have a good 4 days hanging with a friend I don’t see all that often and had 2 great days of fishing. The wind was killer the last 2 days (along with the weird dog), so ending on a skunk note sucked. I’ll be back at some point, Copahee was awesome as always.

All my pictures can be found here.





Android Single Account, Multiple Application Prescription

23 09 2011

One of the really neat things that Google has done with all of its Android applications is that they all share a common authentication mechanism in Accounts and Sync. There is no need to enter your Google credentials for each Google based application on your device, which centralizes password changes to a single location. It also groups those common authentication applications together in the Accounts and Sync settings activity, as I’m sure everyone is familiar with:

device-2011-09-16-084016-2011-09-23-09-03.jpg

For my employer, we have several internal Android applications under development and we too wanted to employ this single mechanism to support multiple accounts paradigm in use by Google. How to do it is in the documentation, but I had to hunt for it a bit. How you obtain the token in the authentication mechanism and how you use that token in your service call is out of scope for this prescription. However, this prescription will show you how to tie all these pieces together:

1. Create your authenticator (out of scope for this).  Consult a previous blog I have on this subject for that prescription.

2. In the manifest for the application containing the authentication mechanism, alter the sharedUserId and put a static value.  Here, we’ll use com.captechventures.mobile.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.captechventures.android.authenticator"
      android:versionCode="1"
      android:versionName="1.0.0"
      android:sharedUserId="com.captechventures.mobile">

3. In the authenticator descriptor (authenticator.xml in my example), add an label to give the grouping of accounts a generic name. While not necessary, this will allow you to name the account something other than the name of the application it’s installed with (default behavior).

<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.captechventures.mobile"
    android:icon="@drawable/icon"
    android:smallIcon="@drawable/icon"
    android:label="@string/auth_token_label"
/>

4. Create the 2nd (or 3rd, 4th, etc) application that needs to leverage that authentication mechanism with a sync adapter. Follow the prescription outlined in step 1, however skip the steps to create the authentication mechanism. You’re still going to need a SyncAdapter.

5. In the sync adapter descriptor (syncadapter.xml in my example), specify the same account as defined by the authentication mechanism created in step #1 in the accountType attribute.

<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:contentAuthority="com.captechventures.test.hc1"
    android:accountType="com.captechventures.mobile"
    android:supportsUploading="false"
/>

6. In the 2nd application’s manifest, specify a sharedUserId value and use the same value that was used in step #2. Optionally, provide a sharedUserLabel as this will be the name of your application under the account grouping.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.captechventures.test.hc1" android:versionCode="1"
android:versionName="1.0" android:sharedUserId="com.captechventures.mobile" android:sharedUserLabel="@string/app_name">
<uses-sdk android:minSdkVersion="8" />

7. When ready to publish your application, you must sign your 2nd application with the same certificate used to sign your first app. Without signing your application, Android will not allow your two apps to share resources (which you’ve specified you’d like to do with the same sharedUserId attribute in the manifest).

You now have 2 applications that can share/use the same authentication mechanism to your back end services! This makes credential management much easier on the user of your apps. A couple of points to remember:

1. When you request a sync with a content resolver, you MUST provide the Account with the appropriate accountType created in step 1 in the API call.

2. Clients are responsible for identifying if the authentication token is invalid, by making an API call to the AccountManager.

mAccountManager.invalidateAuthToken("com.captechventures.mobile", authToken);

3. The 2nd application requires that the 1st application be installed on the device for it work. You should install the authenticator with an application that will always be on your users’ devices or think of breaking that mechanism out into its own application.








Follow

Get every new post delivered to your Inbox.