Skip to content

Responsive Design Challenge: Content Prioritization

September 27, 2014

Determining what content is most important and how to arrange it to reflect priority is a challenge in web design for any device, but becomes even more difficult when considering a responsive web design.

A site designed with Responsive Web Design techniques dynamically changes layout depending on the screen size and orientation of the device being used to view it. The fundamental techniques, as described in Ethan Marcote’s Responsive Web Design – proportion-based grid layout, flexible images and media, and CSS3 media queries – may appear to be the perfect recipe to design for a wide range of devices, from smartphones to large-screen displays. A single website delivered to a range of devices is not, however, without it’s challenges.

Differences in device sizes and interaction techniques, and use in different contexts with varying motivations add additional parameters that are not addressed by the fundamental Responsive Web Design techniques alone. Consider a typical rearrangement of content on a responsive site when viewed on a desktop versus a smartphone:

ResponsiveContentShuffle

The content sequence remains consistent, with the columns arranged from right-to-left on on the desktop view becoming stacked top-to-bottom on a smartphone-sized display. On the desktop, the content block on the right side of the page (block number 4 above) is highly visible on the screen, and would be suitable for high-priority content. On a smartphone, a user would need to scroll through several screens before reaching this content, making this a less than ideal placement for important information.

A mobile-first approach to content prioritization can be an effective starting point to counter these challenges. Thinking about the importance of information in mobile use cases – what should be the most easily discoverable, what could possibly be hidden by default, and what may not be needed at all – can guide positioning content for optimal mobile user experience. Mobile device users expect equivalent functionality and content, however, so it’s important to avoid the temptation of eliminating content and over-simplifying the mobile interface.

Collapsing content, or moving it to secondary screens can make content available while reducing the amount of information a user needs to scan on one screen. The example from Wikipedia, below, illustrates this – the first, summary section is displayed, but each secondary section is collapsed under its heading. The easily scanned list of headings allows a user to quickly understand the content that is included in the article, and the content is never more than one tap away.

WikipediaResponsive

If context of use changes enough between desktop and mobile use cases, it may be desirable to rearrange content. This can be achieved with the CSS3 Flexbox. For example, the following CSS could be used to order content blocks laid out in columns left to right on a wide display:

#container {
    display: flex;
}
#content1 {
    order: 1;
}
#content2 {
    order: 2;
}
#content3 {
    order: 3;
}

Now, let’s say we want to rearrange the order of our content blocks in a smartphone-sized view so that the content from the third column on a wide display appears second, and therefore higher on the page when the content blocks are stacked vertically. We can use the order properties inside a media query targeting smaller displays:

@media only screen and (max-device-width: 480px) {
    #content2 {
        order: 3;
    }
    #content3 {
        order: 2;
    }
}

Simply by changing the order property on the content elements, we can reposition the content for an ordering that is more appropriate to the mobile experience.

A word of caution on CSS3 Flexbox – the implementation of this feature has undergone an interesting evolution, and although current browsers support the new specification (with a prefix in the case of Safari), implementations in older versions vary, and IE had no support at all until version 10. Mobile browser support is generally good, though, so a strategy of laying out content according to desktop priority, and rearranging for mobile can be effective. CSS-Tricks provides a “Complete Guide to Flexbox” that goes into all the gory details for browser support, and even provides a convenient SASS mix-in to help out with browser specific prefixes.

Successful partnerships…and when they are not

August 20, 2014

When striking out on your own to establish a name for yourself, should you resist or embrace partnering with other organizations to deliver your service? The fear being that you might dilute your presence (your name) in the marketplace. There’s definite pros and cons to either answer but on the balance, and based upon our practical experience, we wholeheartedly believe in embracing partnerships.

We’ve found great success in partnering with organizations, particularly ones much larger and more established than us, to bring value to customers that we may not have otherwise had the opportunity to do business with. We have also found through practical experience that partnerships work best when all partner organizations can directly contribute to the delivery of the services. We’ve experienced less success when a partner contributes only in name, e.g. does not directly contribute in the delivery of services or provision of product.

Because we focus on developing mobile Apps for the business sector (companies, government organizations and non-profits), most Apps we build are highly integrated. They are extensions of broader company systems. Changes or modifications to back-end source systems to accommodate the App are invariably needed, something we do not generally do when developing our Apps.

Our best partnerships are therefore with organizations who have an interest in and a right to those back-end source systems. Our unified proposition to a customer is to ‘mobilize’ a particular service or offering and we look to make our impact (and money) from our respective services in accomplishing that objective, without overly relying on marking up the partner’s services in order for others in the partnership to benefit (monetarily, that is).

We have found ourselves in this latter situation (the one being marked up). It generally occurs when a partner organization has an established, and potentially exclusive, presence with a customer yet do not have an interest or right to any peripheral components or services that we are providing (i.e. developing the App for the customer). The partner organization is relegated to simply fronting the engagement (they have a “ticket to the show”) but look to monetize that position by marking up our services.

We’ve seen this make us price non-competitive in many situations and therefore lose the business (and/or damage our reputation). And in the odd case when we’ve still won the business despite not being price competitive, the overall experience was less than optimal since the fronting organization feels a need to be involved in some form (which is understandable, there’s a natural inclination to want to directly deliver value to your customers). This only serves to introduce overhead, however, (i.e. ‘getting in the way’) that those delivering the services could do without.

In short, we wholeheartedly believe in partnering as a way to deliver value to more customers than we possibly could on our own. The caveat being the partnership has to be such that all organizations in the partnership are contributing to the delivery of services or provision of product. Any thing less introduces overhead, bureaucracy and inflated prices making the partnership less sustainable over the long haul.

Responsive web and IE 7 – can we just get along?

August 3, 2014

When it comes to responsive web design, IE 7 is pretty far from people’s minds these days. With global usage of IE 7 having dropped to under 1%, more and more sites and web frameworks are dropping support for this 7-year-old browser. But who makes up that 1% you ask? In our experience: paying customers. Many organizations are still running IE 7, or default newer IE versions to run in IE 7 compatibility mode to get more life out of some mission-critical system or another. So while the rest of the world may be getting on with things, working with corporate IT still makes IE 7 a consideration.

But neither do we want to degrade our web experiences for newer, hipper, shinier devices and browsers. The growing usage of smartphones and tablets demands attention, so now we’re pulled in two directions. How do we cater to a new diversity of devices and browsers while still maintaining a usable experience for desktop users who may have no choice but to use IE 7? Here are some basics techniques to make this work.

Make IE do what it can

IE 7 and later supports three document modes: “standards” mode, “quirks” mode and “almost-standards” mode.  Standards mode provides the greatest support for modern web standards such as HTML5, CSS3, and SVG – precisely the tools we want for responsive design and mobile-optimized web development. Telling IE to render in “standards” mode will ensure that newer IE versions that support these capabilities will actually utilize them, rather than defaulting to, say “IE 7 compatibility.” To instruct IE to run in standards mode, add a doctype as follows:

<!doctype html>
  <html>
    <head>
      <title>The start of something good</title>
    </head>
    <body>
     ...   
    </body>
</html>

Instructing IE to render in standards mode helps us by ensuring whatever standards support is available is actually applied, but this doesn’t help our users running true IE 7 (or IE 8 for that matter) – those browsers don’t implement these modern web standards, and no document mode it going to make that standards support magically appear. We’ll need some Javascript for that!

Make media queries work

CSS media queries allow you to apply different style depending on the characteristics of the device and “media type” (screen, print, TV, etc.). This is a widely used feature in responsive web design to apply different styles – layout, typography, and graphic elements – to tailor the page rendering to the size of the device. IE versions prior to 9 don’t support media queries, and so may not apply the expected styles.

Using Javascript we can conditionally include a script that will interpret and apply our media queries – for example respond.js – so IE 7 users see the page style we want them to (typically the “desktop” view of our responsive pages).

<!--[if lt IE 9]>
  <script src=“/path/to/respond.js"></script>
<![endif]-->

This javascript approach allows media queries for different views to be included in the same CSS style sheet files. The conditional around the script include ensure that only IE less than version 9 will include the respond.js script – from IE 9 on, CSS media queries are supported, so we don’t need the additional overhead of the script.

Add support for HTML5 semantics

HTML5 introduces a new set of semantic markup elements, and while these are not necessary for responsive web design per se, HTML5 semantic markup helps make pages more terse, readable and interpretable for automated processing.

There are a number of Javascript solutions that will define HTML5 semantic markup support so that they can be used with older versions of IE. We usually go with the widely used html5shiv, which you can add as follows:

<!--[if lt IE 9]>
  <script src=“/path/to/html5.min.js"></script>
<![endif]-->

Again, the conditional here ensures that only IE versions prior to 9 will bother loading and running the script, since from IE 9 on HTML5 semantics are supported.

Combining these steps, a starter page for a responsive website that also supports IE 7 would look like this:

<!doctype html>
<html>
  <head>
    <title>The start of something good</title>
    <!--[if lt IE 9]>
      <script src=“/path/to/html5.min.js"></script>
      <script src=“/path/to/respond.js"></script>
    <![endif]-->
    <link href=“styles.css" media="all" rel="stylesheet" type="text/css">
  </head>
  <body>
     ...
  </body>
</html>

There are still many modern web standards we haven’t accounted for here. Features like CSS3 gradients and shadows and SVG that help make a site look great on devices with different sized screens and high density displays aren’t going to do a thing for IE 7. More Javascript solutions can be brought to bear (CSS3Pie for many CSS3 properties, Raphaël for SVG support), but how much of this must be done for IE 7 really depends on your scenario. All these solutions add complexity and overhead, so delivering a functional, if perhaps not optimal experience, that is lighter weight and easier to maintain may be best to deliver responsive design to modern browser users, while not leaving IE 7 users behind.

A Place for Traditional Project Planning?

July 15, 2014

In this age of agility and ‘getting things done’ over ‘talking about getting things done’, it’s often asked if there is still a place for traditional planning, particularly at the outset of a project or consulting engagement. For us, the answer is yes.

We find it particularly useful to commission each project or consulting engagement with a work plan. Our work plans are documents not too dissimilar in content from project charters or project statements that one might find in any well structured, process oriented environment. We call ours a “work plan” largely for connotational reasons. Yes, we do want to plan but only to the extent of understanding and conveying what work needs to be performed to achieve what outcomes or deliverables over what period of time for what budget.

There’s still a heavy focus in our work plans on ‘getting things done’. We shoot for the minimal amount of information needed to crisply and clearly convey the plan of attack to ensure that everybody is on board with that plan. And that applies not only to our customer stakeholders but to our own internal team as well. The process of developing the work plan helps bring our own team into alignment on the work that needs to be done, over what time and what expense allowing them to forge ahead when it comes to Sprint Planning and Development.

Project charters and project statements can fall prey to ‘talking about getting things done’, articulating ad nauseam every minute dimension of a project to the point that it takes weeks to develop, serving only to delay what is of true value, execution. And they become so voluminous that no one gets through them let alone understand them.

Our work plans tend to be no more than 10 pages long and take no more than 2-3 days to develop. The very same week that we kick-off a project, we will have developed and agreed the work plan, enabling us to move very quickly into execution with everyone on the same page in terms of the way forward.

Once the work plan is complete, we extract the relevant information and enter it into our online work management systems for on-going tracking and monitoring. We never come back to the document. That becomes shelf-ware. Instead, we rely upon the status, discussions and decisions recorded in our online work management systems to convey the state and direction of a project at any given time.

For example, we’ll extract the work schedule from the work plan and enter that into the calendar in Basecamp (that may then become tasks in Tick, which we use to track time when operating under a time and material arrangement). We’ll then update the Calendar in Basecamp (and Tasks in Tick) as necessary throughout the project, removing the need for us to ‘issue’ a new project schedule. The project schedule is inherently issued as it is updated in Basecamp and it’s there for everyone to see real time, when and as needed.

Similarly, we’ll extract information relating to work breakdown, in particular the features of the App to be worked on, and enter that into Trello, which we use as an online Scrum board. Again, as changes occur to the feature composition of an App, we simply reflect that in Trello as opposed to going back and updating our original work plan.

In summary, we believe there is still a place for traditional planning in the age of agility particular to help kick start a project or consulting engagement. Once started, however, we then move into a more dynamic mode of planning (e.g. sprint planning) and tracking and monitoring of progress.

A-B testing – it’s about what we know

July 1, 2014

In his post about keeping Apps relevant and prevalent, Rick wrote about the importance of ensuring Apps are functionally relevant to those using them, that they are fit for purpose and contain features that help, not hinder or get in the way. App analytics provide insight to what features are being used, by which users, for how long, etc. But where do we look to answer how under-performing features can be improved?

This is where A-B testing can come in to play. A-B testing is a simple way to test small changes to user interface elements against the current design and determine which variation produces better results. It is a method to validate that changes improve how many users take some desired action – the conversion rate – before those changes are deployed for all users. The high-level process for A-B testing can be illustrated as follows.

A-B Testing Cycle

The process begins with a hypothesis – a change that is thought to produce an improvement in conversions. A-B testing shows the two versions of the UI to different users, and lets user behaviour determine the winner. Running an A-B test takes the guesswork out of optimization, and shifts design conversations from “we think” to “we know.” Over time, repeatedly testing and optimizing improves the overall user experience and provides valuable insight about user behaviour, helping the organization to learn what design practices are most effective for its target audience.

A-B testing has been in use on the web since the early 2000’s. Google was a pioneer of the experimentation approach to design, famously testing variations of their search algorithm to gauge effectiveness. Facebook recently made headlines with their A/B Testing practices, but it is a common practice now among many companies large and small. Recently, A-B testing has been making it’s way into native mobile App development. Optimizely, a leading A-B testing platform, now provides a native iOS SDK that, once integrated into an App, makes it possible to create variations in the native user interface, without resubmitting to the App store.

A-B_mockup

While A-B testing is certainly not the only technique you should consider when it comes to optimizing your user experience, it has some distinct advantages:

  • Results are quantitative, so you can say with confidence which variation is the “winner”
  • It’s very good at accurately measuring the effectiveness of small changes
  • It’s an excellent way to unambiguously resolve design trade-offs
  • Especially when supported by a good tool, it can be done rapidly and inexpensively

A-B testing is not, however, effective is for measuring the impact of sweeping design changes. With a major overhaul of an App user experience, the comparison that  A-B testing relies upon for systematic measurement is no longer possible. Qualitative input from user feedback (App store reviews, user surveys and/or direct observation of user behaviour) is more insightful for identifying “big” user experience problems and measuring the effectiveness of the correspondingly big user experience changes.

When used as part of an overall usability and optimization strategy, though, A-B testing provides reliable and actionable feedback on design choices. With it’s focus on small, incremental improvements, A-B testing is a valuable technique to help ensure App functionality is continuously improved to optimize effectiveness and remain relevant to users.

Beyond Break-Fix: Keeping Company Developed Apps Relevant and Prevalent

June 16, 2014

Most think of managing company mobile Apps beyond their initial development as simply keeping them running, defect-free. But what about how relevant those mobile applications are to those using them? And are those using them representative of the target market, i.e. audience and size, whether those Apps are for internal or external company use?

Apps can be defect-free but contain features that are not relevant to those using them. Or, Apps can be defect-free, contain features highly relevant to those using them but those using them represent a very small portion of the target audience. To maximize return on development investment, the ongoing management of company Apps must be a program of work that goes much beyond keeping Apps running defect-free.

Don’t get me wrong, ensuring Apps remain operational and defect-free is fundamental, whether that involves remediation to keep the App functioning appropriately under new versions of the underlying mobile operating system or remediation of undesired results and experiences surfaced through some unforeseen usage scenario. A highly operable App is core to is existence and sustainment. Most get this. To the point that this is all they focus on. Keeping it running. How it’s being used and who’s using it often goes unmetered.

How many examples of management now buying in to the need for company Apps and funding their development only to watch those investments dwindle away as the Apps suffer premature deaths due to insufficient usage and uptake (not because they were inoperable or defect-ridden). Yes, sustaining company Apps requires those Apps to be first and foremost operable and defect-free. But once that it is achieved, it is necessary to ensure they are functionally relevant to those using them. That they are fit for purpose and contain features that help, not hinder or get in the way.

This requires monitoring the usage of those Apps including features being used, number of user sessions, session lengths, etc. This information is invaluable to the feature roadmap for the App. Why are certain features not being used? How can usage of those features be increased or improved? Should those features plain and simply be dropped or deprecated? How can the number of times a person uses the App be increased? How can the duration of each usage session be optimized, possibly increased? Usage analytics help surface these questions and more importantly serve to stimulate responses to them.

Equally important is monitoring the uptake of company Apps including the number of downloads or installs, rankings, ratings, reviews and even revenue (if those Apps are sold). Who is using the App? Where are they from (e.g. from what part of the company or if external, from what regions)? Do they represent the target audience? How can downloads be increased? How the App’s ranking (i.e. make it easy for people to ‘find’ the App)? As with usage analytics, market analytics help surface these questions and more importantly stimulate responses to them.

A healthy balance of keeping Apps defect free with monitoring their usage and uptake to ensure that features are relevant to the targeted audience contributes to the App’s longevity and enhances the realization of business benefits sought from that App. Most focus solely on the former (keeping App’s running defect-free). Don’t forget the latter, making sure they are relevant and prevalent in the marketplace, even if that marketplace is an internal company audience.

Location Monitoring in iOS

June 1, 2014

Location awareness is a powerful feature we often leverage when developing custom mobile Apps. Whether for delivering location-specific data, tagging user created content, or providing current position for mapping Apps, location awareness provides context and a personalized user experience.

Frequent requests for location data and a high degree of position accuracy will both result in the device location services running more continuously and drawing significant battery power. If the App tracks location in the background, this can cause rapid and, from the user’s perspective, unexpected battery drain. In a recent project, we had a requirement for continuous location monitoring, even when the App was in the background, so it was crucial to tailor the location monitoring strategy to conserve power while still maintaining an accurate enough position to achieve our desired user experience, which was to have the App respond to movements between geographic regions.

The iOS Core Location Framework provides several services we could choose from to meet our requirements:

  • The significant-change location service, which provides a low-power way to get the current location and be notified when significant changes occur.
  • The standard location service, which offers a highly configurable way to get the current location and track changes.
  • Region monitoring that lets you monitor boundary crossings for defined geographical regions and Bluetooth low-energy beacon regions.

While region monitoring sounds very promising for our scenario (geographic regions!), unfortunately Core Location currently supports only circular regions (defined by a centre coordinate and a radius). In our scenario, the geographic regions were decidedly not circular, so we looked to the other options and arrived at a solution with a combination of significant-change location tracking while the App is in the background, and higher accuracy standard location tracking when the App is running in the foreground. This allowed the App to sufficiently “keep-up” with location monitoring when in the background, then have a position “correction” with high accuracy when the user began to interact with the App again.

To allow for location monitoring in the background, we specified the location value of the UIBackgroundModes key code in our App plist file (see update on this below). This can be set through Xcode by selecting the project in the Navigator pane, then checking the corresponding option under “Capabilities” as shown below:

backgroundlocationmode

JULY 1, 2014 UPDATE

As noted in Apple’s documentation for UIBackgroundModes, these keys should be used sparingly and only by apps providing the indicated services. Apple will enforce this during submission review. For location monitoring, the location background mode is only required to use the standard location service when the App is in the background. If you use only the signifiant location change interface to receive location events in the background, then the location background mode is not required.

In code, we used two CLLocationManager objects so we could start and stop the connection to the corresponding location services independent of one another:

CLLocationManager* foregroundLocationManager;
CLLocationManager* backgroundLocationManager;

We instantiate these objects and set the necessary properties to control the location service behaviours:

backgroundLocationManager = [[CLLocationManager alloc] init];
backgroundLocationManager.delegate = self;
backgroundLocationManager.activityType = CLActivityTypeAutomotiveNavigation;
backgroundLocationManager.pausesLocationUpdatesAutomatically = YES;
 
foregroundLocationManager = [[CLLocationManager alloc] init];
foregroundLocationManager.delegate = self;

For the background location monitoring, we set activityType to CLActivityTypeAutomotiveNavigation and pausesLocationUpdatesAutomatically to YES. These settings combine to let the location service monitoring pause when the device detects that it’s no longer moving as it would during vehicle travel. In our scenario we only needed an approximate location fix when the App was in the background, and if the device was not moving “fast” (i.e. being driven around), we could safely pause location updates. This turned out to save significantly on power consumption when the App is in the background, when users would not expect a large battery drain.

Next, we start the relevant type of location monitoring:

[backgroundLocationManager startMonitoringSignificantLocationChanges];
 
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
    [self startForegroundMonitoring];
}
 
[[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(startForegroundMonitoring)
    name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(stopForegroundMonitoring)
    name:UIApplicationDidEnterBackgroundNotification object:nil];

The call to startMonitoringSignificantLocationChanges starts our power-friendly significant location change monitoring that we’ll continue to run even when the App is in the background. We only start our higher-accuracy, and therefore higher power consumption, foreground monitoring if the App is in the active state (i.e. in the foreground). We also register to be notified when the App state changes, so we can turn foreground location monitoring on and off in our startForegroundMonitoring and stopForegroundMonitoring methods respectively:

- (void)startForegroundMonitoring {
    [foregroundLocationManager startUpdatingLocation];
}
- (void)stopForegroundMonitoring {
    [foregroundLocationManager stopUpdatingLocation];
}

When the App enters the foreground, the startUpdatingLocation method is called, starting the standard, high-accuracy location service monitoring. It takes a moment – usually a second or two – for the App to get a location fix, but this is OK since we’ve been monitoring in the background, and have an approximate position already. The foreground location fix ensured that if we were near a boundary transition, that the App would “correct” itself when the user began interacting with it. When the App returns to the background, the call to stopUpdatingLocation ensures we disconnect from the high-accuracy location service to avoid heavy battery utilization.

Can you still be agile when your customers cannot?

May 19, 2014

The short answer is “yes”. Definitely, yes!! We follow an agile approach to mobile software development (Scrum, in particular). Occasionally, we find ourselves in situations where our customers are not able to be agile. The reasons vary but more often than not relate to established internal processes that must be followed, whether that’s willingly or unwillingly.

Despite this, we will still execute in an agile fashion, behind the scenes. We’ll partition work into bite-sized components, validate and prioritize that with the customer, track work on a sprint board (albeit internally), hold daily scrums and share works-in-progress often (rarely do we find a customer that does not want to frequently see what you are working on). Behind the scenes, we’re very agile. On the surface, we’re compliant with the customer’s established practices.

We’ll always execute these engagements under a time and material basis since our template processes, techniques and deliverables cannot be fully leveraged. You come to understand the risks of an approach that you have repeatedly used and have a template for. Those risks can be managed very well, allowing for us to fix-price our services. The risks of following someone else’s approach, however, are not so well understood and therefore hard to predict and mitigate. That’s why we execute such engagements under a time and material basis.

Sometimes, we find ourselves in a hybrid situation, fully following our template agile approach under a fixed-price basis supplemented with customer specific processes and deliverables under a time and material basis making us compliant with established internal practices. This is often the case when the customer sponsor (“the business”) wants to reap the benefits of an agile approach but gaining approval (from “IT”) to deliver against an alternative approach proves too difficult. A middle ground is struck seeing an agile approach at the core supplemented with activities and deliverables needed to be compliant.

Other situations we encounter that suggest an agile approach may not be appropriate include not being collocated with the customer during the software development process and the customer not being able to commit the time. We’ve been able to overcome these perceived hurdles by making use of online tools such as Basecamp and Trello for team collaboration, project management, and work (task) management. These tools help bridge the collocation gap as well as facilitate participation and timely input by allowing customers to contribute when most convenient for them during the day (or night). These tools have mobile versions as well allowing for contributions while on-the-go, in whatever micro moments the customer may have, e.g. while in transit between meetings, waiting in line at the coffee shop etc.

Agile

Handling connection restore in iOS

April 30, 2014
tags:

With very few exceptions, mobile Apps connect to services over the Internet to retrieve and send information. Since we have to expect the connection state of mobile devices to change frequently (switching between networks, in-and-out of cell coverage, etc.), responding to connection failures is a very common task. In many of our Apps we’ve found it useful to implement what one might term a reactive-then-proactive pattern for handling connection failure and restore:

  1. Try to make a connection, for example, to download some data
  2. In reaction to that connection failing, start monitoring for a change in connection status
  3. When the connection status changes, if we can connect to our host, then stop monitoring connection status and proactively try the connected-operation again (i.e. go to step 1). If we still can’t connect, keep monitoring for a change in connection status (i.e. stay in reaction mode, and repeat step 3 whenever the connection status changes).

For iOS Apps, we encapsulate this pattern in a utility class which leverages Apple’s Reachability sample and NSNotificationCenter to accomplish the connection status checking, and a block type to allow a consuming object to specify a callback for connection status changes.

The relevant parts of the utility class look like this:

#import "Reachability.h"

typedef
void(^ReachabilityChangedBlock)(NetworkStatus status);

@property (readonly, nonatomic, strong) Reachability* hostReachable;
- (void)observeReachabilityChangedUsingBlock:(ReachabilityChangedBlock) block;
// Replace this hostName with whatever host you're connecting to
NSString* hostName = @"www.artermobilize.com"
_hostReachable = [ReachabilityreachabilityWithHostName:hostName];
...
- (void)observeReachabilityChangedUsingBlock:(ReachabilityChangedBlock) block {
[[NSNotificationCenter defaultCenter] addObserverForName:kReachabilityChangedNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
Reachability* reachability = note.object;
if (reachability.currentReachabilityStatus != NotReachable) {
// If we're able to connect, stop observing reachability // changes. The caller can call the method again in // reaction to another connection failure. [[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];
}
block(reachability.currentReachabilityStatus);
} ];
[_hostReachable startNotifier];
}

Then, the calling code simply needs to supply a block to handle a change in network connection status. For example:

    [network observeReachabilityChangedUsingBlock:^(NetworkStatus status) {
        if(status != NotReachable) {
            // Perform work after re-connecting, e.g. fetch some data
            [self fetchSomeData];
        }
    }];

Exception recreating Android Fragment after App dies in the background

April 16, 2014

On a recent Android development project, we encountered a tricky, and at first difficult to reproduce issue. We would open the App, either from the recents list or the launcher icon, and the App would immediately crash. Start it again, and everything was fine. Digging into the logs, we found that there was a consistent exception:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.artermobilize.aea/com.artermobilize.aea.MainActivity}: java.lang.NullPointerException
     ...     
Caused by: java.lang.NullPointerException
     at java.util.ArrayList.(ArrayList.java:93)
     at com.artermobilize.myApp.ItemListFragment.onCreateView(ItemListFragment.java:73)
     ...

The offending line of code was in the first line in the onCreateView method in a fragment class, which looked like this:

@Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      AlertAdapter adapter = new ItemAdapter(inflater.getContext(), 
R.layout.alert_row, new ArrayList<Alert>(items));
      setListAdapter(adapter);
      return super.onCreateView(inflater, container, savedInstanceState);
 }

It was pretty clear from the stack trace that the exception was happening because the items variable we were initializing the ArrayList with was null when onCreateView was executing. When stepping through the code in the debugger, it always had a value, so what gives?

I finally came across a StackOverflow post that pointed us in the right direction. The key comment there for us was:

… the application is restored to its previous state because it was killed by the OS due to low memory while it’s in the background. Upon task switching back it’s restored to that previous state …

When an Android App is killed in the background, when you then task switch back to it the OS will try to restore the Activity/Fragment that was last in the foreground. This does not follow the same sequence of execution as when the App is first launched. In our case, the items variable was be populated from data contained in a static variable in another class. That static variable would be trashed by the OS along with the rest of the App, and the code to populate it was not being executed because it resided in a different Activity. Understanding how the Activity/Fragment was being recreated now, we were able to readily reproduce the condition by sending the App to the background, and running an ADB command to kill the process, which made the static variable null every time:

adb shell am kill com.artermobilize.myApp

With that realization, our solution was to reload the static variable if it’s null when the Fragment is created. We wanted “fresh” data anyway, so in our scenario this made sense. Another possible approach would be to hook into the default Bundle instance state, which the system already uses to store the state of each View object in order to recreate the Activity/Fragment. Google provides guidance on how to extend this to support recreating an Activity.