Thoughts on Google I/O 2013

18 05 2013

Google I/O 2013 has ended and while we saw a few new things on the Android front, this year’s event was much more dialed back than 2012 as far as the platform is concerned. There was no Android update announced, much to the chagrin of some bloggers. In my opinion, this isn’t that big of a deal as the platform is in a very stable, viable place right now. The platform along with the Android Design Guidelines provide the foundation for developers to deliver almost everything possible in their apps.

There was an update to the suite of services labeled as Google Play Services, which includes APIs such as Maps, Google+ sign-in, Cloud Messaging, and Game Services. How Google is leveraging Play Services is very clever and hints at how Google intends on getting around manufacturers and carriers dragging their feet on OS updates. Google isn’t the reason for fragmentation in the market, it’s the carriers and manufacturers taking months to release updates and in some cases, never releasing them. I think we’ll see more of this sort of update in the future, getting updates to critical APIs in a push that doesn’t rely on carriers and manufacturers to cycle through their own development and test processes.

There was the announcement of Android Studio and a new build system, Gradle. Android Studio is based on the community edition of IntelliJ and while I’ve never used that IDE myself, several of my colleagues have and swear by it. I’ll be taking a closer look over the next few weeks even though the IDE is considered a Preview release. It appears to be pretty functional. While Tor Norbye stated in the intro session they plan on keeping both Eclipse/ADT and Android Studio functionally equivalent, he did let one tidbit slip out that caught my attention. He stated that “some things are just easier to do” and “some things we just can’t do in Eclipse” when discussing the features of Android Studio. This makes me wonder just how viable it will be to expend resources on two different platforms when one is clearly easier to deliver functionality for. Eclipse/ADT may stick around for a year or two, but I wouldn’t be surprised if support is dropped some time in the future.

I’m surprised it took as long as it did for Google to move away from Ant as their build system. As someone who has been using Maven since 2007, I loathe every time I have to look at an Ant script. The move to Gradle makes sense and is even a bit forward thinking on their part. I look forward to introducing dependency management and artifact repositories into my projects.

While there was a strong emphasis on gaming this year with the introduction of Google Play Gaming Services and nearly every period of the first day dedicated to gaming sessions, there were a few things of major interest to the enterprise community. Many, if not all, of our mobile clients are leveraging Google Map APIs in their native applications. I encourage all to revisit their code and take a look at the new Fuse Location provider with significant battery savings.

The biggest announcement for the enterprise centered around the Developer’s console, particularly support for Beta Testing. I wrote a blog over two years ago about Android in the Enterprise and how it just wasn’t ready yet. One of the issues I had was the inability to distribute software internally. That’s been fixed somewhat by the addition of a private channel for Google Apps customers, although I’d like to see this expanded a bit to allow enterprises to also leverage this feature. However, at nearly every one of my clients we’d have to figure out a way to distribute an application to our testers for system testing. This almost always involved system admins, network admins, etc to get some hosted disk space on an Apache server, email blasts to all the testers with a URL or IR code for them to download. This should be a thing of the past with the new Beta Testing feature. Smaller enterprises could even leverage this feature to target their production internal applications via this channel. While I’m most excited about this feature, the full fledged integration of Google Analytics right into the Developer Console is also a welcome addition. Provided you’re using GA for analytics in your app, all this information will be side by side with all the other analytics you get for free from the Google Play Store.





Android targetSdk and the Legacy Soft Menu Button

5 11 2012

At Google I/O 2012, Google made it a point to stress that Android developers should be leveraging the highest API level for the targetSdk attribute in our application’s manifest. They stated that essentially it should be the latest version of Android available. As I hadn’t been doing this in the past, when I got back to the client site I immediately started setting this attribute to the latest version available, API level 16 (Jelly Bean).

What I didn’t realize, is that this attribute determines whether or not the legacy Menu button appears in the soft key button tray for devices that only have soft keys. If your application isn’t up to the design standards that Google recommends for ICS+ and you have legacy menu options in your application, you’ll need to ensure that the API level you specify for targetSdk is no greater than level 10, Gingerbread. If you specify anything above that, your users will lose their ability to use Menu options.





Programmatically Locking Android Orientation

6 10 2012

On my latest project, we had some technical requirements to lock the screen in the current orientation while some background processing occurred. Once the processing was completed, orientation is returned back to whatever the orientation was before it was locked. This seemed pretty straight forward as there are several examples around the net on how to lock in portrait or landscape. Locking on the existing orientation didn’t seem that difficult, use the existing orientation value:

orientation = getRequestedOrientation();
setRequestedOrientation(orientation);

This seems pretty straight forward, until you take a look at the javadocs (or in my case, have a defect arise). We found our locking code was working when in portrait mode, however it was not working when in landscape and orientation changed to potrait. Adding some debug code and we found out when in landscape, user orientation was being returned. Looking at the javadoc, user orientation is defined as:

The user’s current preferred orientation.

This user value can come from system settings and could of any value, so we can not confidently code for the appropriate orientation. I’m unsure if it’s a defect in the platform or if it were designed this way, but locking the orientation on this value does not lock the current orientation

The absolute best way to programmatically determine orientation is to use a combination of screen width, height, and rotation. Rotation is defined with constant values of 0, 90, 180, and 270. A phone’s natural orientation is portrait, so it’s base rotation is value for portrait is 0. That means that landscape rotation could be 90 or 270 and with the phone completely flipped upside down rotation is 180. A tablet’s natural orientation is landscape, so it’s base rotation value for landscape is 0. That also means a tablet’s rotation could be 90 or 270 for portrait, and 180 if it is landscape but flipped upside down. This rotation value in combination of screen size (i.e. is x greater than y) gives us a true representation for orientation and allows us to truly lock the orientation correctly. Keep in mind, you need to account for reverse orientation.

Display display = getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();

Point size = new Point();
display.getSize(size);

int lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

if (rotation == Surface.ROTATION_0
		|| rotation == Surface.ROTATION_180) {
	// if rotation is 0 or 180 and width is greater than height, we have
	// a tablet
	if (size.x > size.y) {
		if (rotation == Surface.ROTATION_0) {
			lock = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
		}
	} else {
		// we have a phone
		if (rotation == Surface.ROTATION_0) {
			lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
		}
	}
} else {
	// if rotation is 90 or 270 and width is greater than height, we
	// have a phone
	if (size.x > size.y) {
		if (rotation == Surface.ROTATION_90) {
			lock = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
		}
	} else {
		// we have a tablet
		if (rotation == Surface.ROTATION_90) {
			lock = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
		} else {
			lock = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
		}
	}
}




James River – Huguenot Flatwater – 5-13-2012

13 05 2012

Got out for about 2.5 hours today on Huguenot Flatwater. I’ve fished this stretch well over 20 or 30 times and haven’t had much luck. Since I only had a few hours today and needed to get on/off fairly quickly, I just hit it in hopes I’d land a couple of fish.

As I was putting in, a young guy was coming off the water. He said the current was ripping, the wind was pushing downstream as well, and fishing was tough. He said he didn’t catch anything so I wasn’t expecting much. I forgot my Hawg Trough so without hope of catching anything significant, I entered the water care free.

Got on the water and the water was high and fast. I remember a hand drawn picture I’ve seen that Jeff Little drew, a profile view of ledges and eddies and how to fish them in high and low water. That drawing showed fish holding tight upstream in the eddie, so that’s where I concentrated today. Normally there are tons of visible rocks to wedge yourself on and fish off of, today there were only a dozen or so…

First one I come to, I throw a Mann’s Baby Waker in a bass pattern to the rock and started reeling in. No more than a couple of cranks and I get a solid hit. After a nice fight I reel in a nice 17″ smallie, my new PB. Again, nothing to measure by I’m going my estimates of my body parts :)

DSCF0866-2012-05-13-19-04.JPG

Release this fish and now I’m beaming. Hit 2 or 3 more of the visible structure, going with the same pattern but no more hits. On the 4th or so, I beach my kayak, throw out the Mann’s about 15 yards downstream, and start retrieving back to the rock. I get a hit…and it was a doozie. It’s the largest freshwater fish I’ve ever seen in person. I got to set the hook and the rod doesn’t bend…FRACK. The knot failed, friggin Rapala knot. I’ve had that knot fail on me the last 2 outings on larger fish. I know it’s the tier and not the knot…. I quickly grab my finesse rod, with a draggin’ head and a Tiki Craw loaded up with Craw Bioscent. Throw it back in the vicinity of the strike, no more than 10 seconds and my line starts moving…go to the hook and the rod doesn’t bend. SONOFA…this knot failed too. W-T-FRACK. Improved clinch, but it failed too (yes I wet before tightening). I quickly real in, grab a weighted tube hook, throw a green tube on, lather it up with Craw Bioscent and throw it back in the area. This time I let is set for what seemed like 3 to 4 mins and the line starts moving again. Set the hook…FISH ON. I can’t believe the size of this smallie. After a nice fight, I land him. HOLY CRAP, I wish I had my Hawg Trough.

DSCF0871-2012-05-13-19-04.JPG

FYI, the inside of the 2012 Ride 135 is 20″. This fish reaches end to end and is also laying over the bump in the middle. I’m guessing this guy went 20.5″ to 21″. Most certainly would have been a Virginia citation. I release the fish and get on about my day.

I catch another dink over the next hour, but not much else. I’m about to wrap up for the day, there’s still 2 visible rocks I haven’t hit. I’m going to leave after these two. On the first one, no action on the Baby Waker. I throw the tube in and let is set for 3 or 4 mins and I think I see hit, but I’m not sure so I don’t set the hook. After 5 or so seconds the line is moving so I set the hook. A nice fight later and I’m estimating this fish at 19″.

DSCF0873-2012-05-13-19-04.JPG

Unfortunately, that extra 5 second wait enabled this fish to inhale the tube. It was gut hooked. I’m always iffy on what to do in this situation, just take the fish home or cut the line and hope the hook frees itself. I do what I always do and cut the line and returned the fish as fast as possible (after a couple of snapshots). I hope that guy lives and reaches 20″+. I decide to call it a day on that one.

2.5 hours fished in an area that’s not rare to send me home with a skunk, 4 fish caught and 3 of them went 17″, 19″, and 20.5+”. Pretty good day for me.

All my pics:

https://plus.google.com/photos/102799211425946575386/albums/5742144187400956049





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.