Two Days at the moosecon Conference

This year the German IT trade show CeBIT tried something new: A conference for mobile developers, called moosecon (mobile operating system conference).

The conference lasted three days, of which I was present at two, Wednesday and Thursday. Here’s a short recap of the talks, I visited.

Wednesday – March 6, 2013 / day one

Thanks to the German railway system I was late. Nearly one hour later than expected. Thus I missed much of the first talk of the conference. And to make matters worse, the conference organizers decided to change the schedule.

HTML5 for the mobile web – Firefox OS
Chris Heilmann, Mozilla

The train delay and the reorganization both resulted in me missing most of Chris Heilmann’s talk about Firefox OS. From what little I could hear of the talk, it probably was the most interesting talk of day one. Especially since I am very interested in Firefox OS.

Those that follow me at Google plus know that I hope for FirefoxOS to become a viable competitor to iOS and Android – even though I remain sceptic of the chance to get there. I think it can only be good for innovation in the field if there is a bit more competition and if there are more open players. I am an Android developer and intend to stay one, but this doesn’t mean that I might not have a look at other systems.

Right now I mostly despise HTML5 apps on Android – simply because they do not fit. They often lack the necessary visual integration into Android and just do not feel right. That’s not too surprising, because right now most apps, if not all HTML5 apps, are created to save money while deploying the same app on multiple platforms. That’s something that simply doesn’t work too well. It has been a problem for Java apps on the desktop for years and it’s no different for HTML5 – so I guess it’s not something that will just vanish when HTML5 gets more mature, it’s API more stable and unified across browsers and so on.

Nevertheless I think there is a place for HTML5: For apps within a browser or if HTML5 apps are first class citizens of the OS as in Firefox’ case. In the latter case the problems that apply to webapps on Android are simply no problems, because all apps are webapps – with probably some kind of standard look & feel as well. Performance problems though might remain.

What I heard of Heilmann’s talk centered mostly around Web-Activities. Those more or less resemble intents. Google had introduced a proposal of Web-Intens before – but from what I understood at the conference, Google doesn’t use those any more and both now work together on Web-Activities (though this was a bit vague).

I still haven’t seen Firefox OS in action and if Chris has shown a live demo I must have been to late for it. But from this talk, I still consider it to be an interesting approach.

If you want to know more about developing for Firefox OS, visit Mozilla’s developer site for Firefox OS.

Effects of Firefox OS
NN,Telekom

Someone from Telekom’s management replaced Martin Kurze, who got ill. I didn’t get his name, but he was pretty high up. Given that he was management it was surpirsing that his slides were the worst ones presented. Whatever you can do wrong on a slide, you could find it here. But apart from that the talk was more interesting than I had expected.

He outlined why the Telekom is supporting Firefox OS. Purportedly because Telekom is all for openness. He made a big fuss about HTML5 and that this is an open standard and what not. Yes, it is and that’s what I like about it as well. But in the case of Telekom I guess it has more to do with them not wanting Google, Apple or Microsoft to be the only ones profiting.

Be it as it may, this carrier as well as many other carriers is supporting Mozilla to create another competitor and to keep relevant and get a share of the revenue. While I couldn’t care less who get’s the biggest piece of the cake, it could prove important for Mozilla in getting some traction – especially in markets in which customers are still using feature phones by a large margin (Telekom for example starts with handsets in Poland).

Successful Inhouse Enterprise Apps
Patrick Blitz, Weptun

This talk centered mainly around two aspects: Security and Connectivity. The talk was too high-fly for me to really like it. Nothing wrong with giving an overview. But moosecon is a developer conference. And as such I would have liked to see some remarks about difficulties and problems in implementing each of the solutions.

Maybe he should have sticked to just covering security. After all connectivity is a problem common to nearly all apps and thus not specific to in-house enterprise apps.

Enterprise apps nearly always have to deal with very sensitive data. Data that has to be kept private – no matter what. I really would have liked to hear more about that.

The bad audio situation didn’t help the talk either. Not the fault of the speaker who spoke clearly and articulate, but of the conference setup. More about that later on.

I think a bit more in-depth coverage of what the biggest problems are (from a developer point of view) would have helped this talk.

Creating Backends in Minutes
Lutz Kohl and Philipp Michel, Apiomat

The speakers presented backends as a service (BaaS) in general and exemplified the key points with apiomat, the solution of their company.

Obviously the speakers had an interest to present BaaS in the best possible light – and they did a good job at this. There are very good reasons for using backend services in the mobile environment. Their main point was that it reduces time to market, that it helps safe costs and that you do not have to care about getting the necessary amount of power and of getting this right. Time to market is probably correct, depending on the flexibility of the BaaS provider. I also think that it’s difficult to estimate the necessary computing power and that for many projects it’s an unnecessary burden to have to think about load balancing, redundancy, failover solutions and what not. So far I’m in the BaaS camp.

But I think the speakers purposefully underestimated the complexity around REST – which will remain independent from using a BaaS solution or a selfmade one. Thus I do not believe their cost estimate at all – but well, of course they were a bit biased :-) Granted, BaaS probably is cheaper, but the difference is much smaller than presented here.

They showed how to use apiomat, how to generate code from their website, where to create custom business logic besides simple CRUD-logic and how to integrate apiomat into your app. Both speakers did a good job, but some stuff could have been a bit more detailed. Also the dashboard and any reports would have been interesting.

Nevertheless BaaS solutions are interesting and can help your project siginificantly. Apiomat is a German solution targeting the European market, so maybe they are the right solution for you. Which BaaS provider to use comes down to a business and a trust decision. The latter is very important since BaaS requires a trustworthy partner. And don’t forget the privacy aspects as well. At least we Germans are very sensitive when it comes to this.

Push Notifications
Benjamin Broll, Little Postman

Benjamin talked about push notifications and how complex this can get – especially if you want to use push for different target platforms. The latter is made worse because each platform has it’s own notification model and each provider handles communication between your backend and the notification delivery service (e.g. Google Play Services for Android or Amazon Device Messaging if you care about the Kindle Fire). He detailed the problems you have to deal with if you want to do so on your own. Well, of course he was on a mission as well – but this part of his talk was really good!

He also stated reasons why push is a good solution and that it might help user satisfaction – especially if you find innovative uses for push – the examples he gave were also interesting to hear.

So far so good. But why not show how to do all that with Little Postman? After all, that’s his company and there’s nothing wrong to present your stuff if your general points are presented in a more or less neutral fashion. I think he missed an opportunity here to drive home the message, that Little Postman could be the solution of choice for you.

Overall impression of day one

I have heard some nice talks but obviously missed a very large part of the most interesting talk. All in all it was too little code and often too high-fly for a developer conference.

But the worst thing was, that it didn’t get the attention that is so important for conferences. Attendee numbers were quite low – especially in the closed area. So one of the great by-products of conferences – being able to meet people you know via the many social channels as well as to network with other devs – was nearly completely missing for me.

Audio quality also was a big problem – at times nearly unbearable. The sound level at trade shows is always very bad. But in this case the open and closed stages were too close to each other, which sometimes made listening unnecessary hard.

Wednesday – March 7, 2013 / day two

I was on time – great. But there had been a shuffling of talks once again. The first two talks at the open stage were swapped. Thus I couldn’t hear the Google TV talk I originally had planned to go to and instead listened to a white-collar talk I hadn’t had on my agenda.

Cross Platform for White Collar Workers
Marcus Ross, Zahlenhelfer Consulting

Marcus is developer and project manager – but in this talk he was all project manager. The title of the talk says it all: It was no technical talk.

Obviously Marcus thinks much more of HTML5 apps as a cross-platform solution than I do. He believes that they can be a good fit for apps, that must run on multiple platforms. He mitigated this by saying that it depends on the requirements, but still…

According to Marcus, often some kind of hybrid is needed where you access certain hardware features via a wrapper API and otherwise use HTML5 to develop your app. Another point of Marcus was, that unless you are doing in-house stuff or cannot use the app market for business reasons (e.g. for publishers the Apple app store often is no option), you should always use at least some kind of wrapper to market-enable your app.

I think though, that this is risky: Putting your app on the platform specific appstore might make marketing sense, but it also sets certain expectations of the customers. I think HTML5 apps should stay on the web, be clearly recognizable as web apps and as such should use a standalone UI that doesn’t try to mimic the native UI. Marcus obviously disagrees and showed samples of apps that try to resemble native apps as closely as possible. Well being an Android native developer, it’s kind of my duty, to disagree :-)

If you wonder how this fits in with my Firefox OS hopes, keep in mind that on Firefox OS it’s a completely different story – there HTML5 is native! And I wouldn’t recommend to use a Firefox OS app on Android within some native wrapper. I have no problems with them though, if they run within a browser!

At the end the organizers started talking at the second stage – which caused many (including me) to leave this stage. But then the talk actually didn’t begin for another five minutes. Sorry, but this shouldn’t have happened. The organizers should have been more careful. It simply was not fair to Marcus.

Ugly thruth about HTML5
Robert Virkus, Enough Software

This talk was some kind of counterpoint to the previous one. Robert prefers native. And it’s not just what I’ve written above, but there are technical reasons why cross-platform is not as cross-platform as management thinks. Most platforms (Microsoft’s Windows Phone OS and Mozilla with Firefox OS being two exceptions) use Webkit as the default rendering engine, but that’s just one part of the story. When it comes to Javascript – and you will need to use Javascript – each vendor uses its own engine. And even worse: Webkit is not the same everywhere. There are tons of compile time flags and Android uses different ones then iOS. Thus you can use some stuff on Android which isn’t available on iOS and vice versa.

Than he mentioned the uncanny valley. That’s a robotics theory stating that when humanoids get more and more close to actual humans people at first like this, until it suddenly changes and people start to strongly dislike those robots – until approval rises again when the humanoid is nearly indistinguishable from a real human.

He applied this uncanny valley theory to mobile apps. People will dislike your app if it tries to be like a native app, but fails to actually deliver. Thus his advice for any HTML5 apps: “Don’t mimic the native UI – use an HTML5 UI”. Couldn’t agree more!

BTW: That’s the reason why HTML5 works for games that do not need native speed. Games most often do follow their own style and thus do not mimic the native UI anyway. And since games never did, customers won’t wonder about this. Instead they expect games to be different. In my opinion games are thus currently the only real option for HTML5 apps.

Mobile Market News
Sacha Pallenberg, MobileGeeks

Well, i don’t know. I’m no big fan of him. But he definitely is a great speaker and he knows his stuff (mobile hardware) very well. Thus this talk was indeed very interesting. His talk was lively and it was obvious that he really enjoys his field and also talking about it. His talk was hampered by severe technical problems (the beamer going off every now and then for roughly two/three minutes) but he managed to work around that effortlessly.

First he talked about SoCs. Something I’m not much interested in.

Interesting though his take on the battle of mobile operating systems and if competitors to iOS and Android can play any significant role. In short: He’s not very optimistic about any of the other platforms – with the exception of Windows Phone. One point for FirefoxOS is that it has the backing of many carriers, but he doesn’t believe that it will help them that much.

What took me totally by surprise was his statement, that Nokia managed to keep it’s ship afloat because of its Windows Phone transition. Huh? Right now I still think this strategy is not working too well for them. But let’s wait what the future might hold. Predictions in this area are not worth too much anyway :-)

Lessons Learned from Prime Guide
Markus Junginger, greenrobot

Finally two Android related talks. Markus talk about Prime Guide – an Android only TV programme app that I highly recommend and use myself – came first. His talk contained some interesting surprises. Lessons learned are always great and probably should be covered more often (on conferences as well as on blogs or in magazines). Why not learn form others?

The Prime Guide team took great care to deliver an outstanding Android experience – a necessity to compete in the crowded TV-programme market. And it can be seen: As a user of this app, I can confirm that it indeed performs well and looks great. The good ratings of the app are another proof that they did a good job.

The devs made heave use of libraries or created some while developing the app. Something Markus recommends highly to all Android devs. But even with using libraries, the app took still way longer than expected – not least because its developers had to move to customer projects and couldn’t work continously on the app. Markus estimated the total amount for the app was more than one person year.

Especially fragments gave them headaches. To quote: “Fragments are one of the most difficult APIs” in Android. Especially together with multi-threading and funny (or rather not so funny) life-cycle issues.

Prime Guide is a good example for why BaaS makes sense. They have two big peaks when it comes to backend hits: In the evening when people actually start to watch TV they use this app the most. From the graph presented it’s an enormous spike and to cope with that, you definitely have to use a cloud based service – or use a set-up that idles away most of the day. The second spike comes from when the server downloads and processes TV programme data.

In his talk, Markus mentioned some problems with app engine. One of them stuck with me: When they started out, AppEngine offered no SQL database. And according to Markus “that’s not cool” at all (so much for the NoSQL rage) – but instead caused them to adapt the data model to app engines’ special needs.

The thing though, that surprised me the most was his statement, that they shouldn’t have published the app for all device categories at the same time. Since I think this app is extremely well suited for tablets, I asked him if they wouldn’t have been missing out had they done a phone only app first. Markus states that they could have released the app much earlier had they made a phone only app. I guess there is no arguing about that. He also states that when they started out Android tablets had not been as wide-spread as nowadaays. Granted, but I still wonder.

Would their initial rating (4.6 in the first week) have been as good? Wouldn’t many have complained and demanded a tablet version? Which might have caused them to rush one with potential implications for the overall app quality. Finally a tablet later strategy might have lead to some serious refactoring when adding the tablet-related aspects later on. With probably even more complexity and headaches. I don’t know. Markus has way more experience than I have, so I really would like you to chime in. What do you think about releasing for the phone first? And is this still a viable strategy – now that many more tablets are in use? Please let me know on G+ or in the comment section.

Oh, and here’s one last but important advice from Markus: Release early! Don’t wait till it’s perfect! Users might have different needs anyway (in their case for example they wanted more channels within the app).

In short: Great talk!

Edit: After reading my draft, Markus send me some clarification about this: In this clarification he suggest to only offer the most essential functionality for tablets right from the beginning and to add more later on. Do not waste time with every detail on every screen for all three versions (Google TV, tablets and phones) but concentrate on phones and only for some especially central screens on tablets. Even with this clarification I still would like to hear your thoughts on this in the comments!

AB-Test Library for Android
Hasan Hosgel, Immobilienscout24

In his talk, Hasan Hosgel presented his library CustomersChoice, that you can use to enable AB-Testing within your apps. It’s an open source Android library and the project page of CustomerChoice is hosted on github.

Hasan first stated why he created it. The point is that product managers often have no clear idea which features are really useful or how to present those features. Usually you create a short user test to find out, but often you still don’t get a clear picture. That’s where this library comes into play.

While ImmobilienScout24 (Hasan’s employer) can afford customer surveys and user tests, small shops or indie developers sure can’t. Thus this library is even more useful.

After this he showed how to use the library. You only need a few lines of code to choose a variation and to report a success – if the user found and used the feature you test.

Configuration needs a bit more code but is still pretty straightforward. Configuration can be done in multiple ways. Either in code or by a JSON definition that the library can download from the web, read from the SD card or get from a resource definition within the app. Here you define the variants and their variations. A variant is one feature you AB-test. A variation is one specific implementation of this variant. So if you want to test which of three colors is the best this would be one variant with three variations.

Each variant has a name you later use in code. They also have optional start and end dates to scope the test. And you can set the ratios between the variations – the default being a uniform distribution of course.

Finally Hasan showed the library in action and it’s integration into his code. You can also download a demo of Customer’s Choice to have a look yourself.

My only beef with this library is it’s name. It suggest a conscious decision by customers about which features to implement in which ways. Which generally is no good idea. You should listen to customers, of course, but which features to implement and especially in which way should be your decision based on user goals, usability concerns, the direction you want to move forward in and the general style of your app. Thus I think CustomersChoice is a misleading name.

So to clarify: This library let’s you find out which possible implementation works best for your user base. Exactly what we sometimes need.

Good talk and an interesting library. I suggest to have a look at it.

How Paypal uses Open Identity
Tim Messerschmidt,Paypal

Now, to be honest: If Tim hadn’t been in my Google plus circles I never would have watched this talk. Paypal is not my most liked service on the web. Apparently I’m not alone with it, because Tim tried to destroy any doubts about using a Paypal solution :-)

First Tim explained the concept of identity within his talk. It’s mainly about authenticating a user. All those “Log in with Twitter” buttons basically allow you to use one account to access multiple websites.

And here is where Paypal comes in. For shopping sites you may not want to use your Twitter account but a more reliable partner that either already has your credit card information or which you trust enough to hand over your payment information.

Paypal uses OpenID Connect which, according to Tim, is much easier to use for us developers than plain OAuth 2 – even though it uses OAuth under the hoods. He explained that OAuth has developed in a direction where you basically need a custom implementation all the time without being able to leverage code reuse. Something that OpenID Connect seems to solve. Whether that’s true or not, I do not know – but I know that OAuth has a reputation of being a mess.

He also showed the different levels of information clients can get from Paypal. As usual the user gets a short list of what is offered by the provider (here Paypal) to the site. In Paypals case this ranges from just a confirmation of the name and the email address to the real-world address of the user to his age information. Finally Tim concluded his talk with a short demo.

Paypal might actually be the appropriate solution in some situations. But for now the only important thing for me is to know that it exists – should I ever have a need for it.

Overall impression of day two

Apart form two things this day was much better. Sound problems were not as pressing – especially since in the afternoon only one stage was used. The problem with the beamer – well this can happen. Not too much of a problem – though they were lucky that it happened while a seasoned speaker was on stage. Totally unacceptable was the early opening of the second stage while a speaker was giving his talk on the other stage. Given the sound condition it was no wonder that many people thought the next talk was starting.

Apart form the first talk, this day was more technical – which obviously is more to my liking. And this day I also met people I knew. I’ve met Hasan Hosgel at last years Google devfest in Berlin and together with others we stayed at c-base for quite some time in the evening. It was nice seeing him again – though I prefer the c-base atmosphere any day! I hope for another devfest this year. I also knew Markus Junginger, Matthias Friedrich (no speaker) and Tim Messerschmidt from Google plus. Great meeting them as well.

How the moosecon should change

I think the moosecon has a future, but it must improve in some areas. It should be more technical and more dev centric – or offer two slots: One for devs and designers and one for management.

Having mentioned designers: I wonder why they aren’t invited as speakers to these events? The design (as well as the usability, which is something completely different) plays an important part in the success of an app – still it’s ignored way too often. I’m a dev, I have no talent at all for design, but even I notice apps that are either too complicated to use (bad UX) or simply visually too off-putting to use. The one problem here of course is that UI and UX concepts of all platforms are vastly different. But so are the programming models.

I think speakers should be instructed to give a technical talk (unless the conference offers the two slots I mentioned above, in which case I only speak for the dev slot). To concentrate on those aspects that are most interesting to fellow devs like problems encountered and tips how to deal with them. Or talk about how to use your libraries/products, how to integrate them.

In general the conference must attract more people. The organizers must concentrate on that. Good talks are one way to achieve this, but not the only one. Maybe more hands-on stuff would help. Some kind of app-dev-contest, hackathon or what not. Or offer some power workshops. It was simply too little content.

Another possibility would be to only use two days but more stages. Given that the early as well as the last talks were not visited well it might also be worth to consider reducing the overall time on stage and offer other things like workshops afterwards.

As a final note: The catering was excellent. Thanks!

Adding ActionViews to Your ActionBar

As you have seen in the previous tutorials about ActionBarSherlock and the ActionBar, you can add action items easily and they show up either in the ActionBar itself or in the overflow menu.

But so far all you could add were normal action items. And those consisted either of icons, of text or of a combination of both – depending on the available space and of the way you configured the items to show up.

That’s not always sufficient. Sometimes you would like to display a custom layout. And that’s what ActionViews are for.

What are ActionViews

Action views allow to display arbitrary layouts instead of the usual icons or texts. They were introduced in Honeycomb together with the ActionBar.

Of course the available place for your layout limits your possibilities. Since – by a large margin – most Android devices are phones, your layout should take this into consideration.

With Ice Cream Sandwich ActionViews were improved further. Since then Android does not always display them fully expanded but allows for a collapsed mode as well. In this mode ActionViews show an icon as usual and only when the user clicks on the icon does it expand to the full layout.

When to use ActionViews

Basically you use ActionViews when you need to replace the icon with something else or when you need a more interactive widget.

Android itselfs comes bundled with the SearchView that adds an EditText widget for search. I will cover this widget in the next section.

Another common use case is to replace an action item with a progress indicator when the action is bound to last longer. Most often this is used together with a refresh action item.

Using Android’s SearchView

Android comes with the SearchView as the only bundled implementation of an ActionView.

I covered all you need to know about searching on Android and search suggestions in previous tutorials. Here I will cover only how to make use of the SearchView.

Let me first show you some screenshots:

Collapsed Searchview showing only the search icon

Collapsed Searchview showing only the search icon


Expanded Searchview showing the EditText field together with the search icon and the search hint

Expanded Searchview showing the EditText field together with the search icon and the search hint


Expanded SearchView with entered text

Expanded SearchView with entered text

The first shows the action bar with the search icon – thus the action view is in collapsed mode. The second screenshot shows the view after the user has clicked on the icon. It expands to an EditText widget together with the search hint of your searchable configuration. The microphone symbol is also the result of the search configuration file. The last screen shows the EditText widget after the user has entered some characters.

If you have added search capabilities to your app, getting the SearchView to support this is pretty easy. All you have to do is tell it about the search configuration. For this you need to get a SearchableInfo object from the SearchManager and call setSearchableInfo() with this object on the SearchView object used for your ActionBar. Well for me code is often the best explanation, so here is what you have to do:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   getSupportMenuInflater().
         inflate(R.menu.activity_actionview, menu);
   MenuItem item = menu.findItem(R.id.actionView);
   SearchView searchView = 
         (SearchView)item.getActionView();
   SearchManager searchManager = 
         (SearchManager)getSystemService(Context.SEARCH_SERVICE);
   SearchableInfo info = 
         searchManager.getSearchableInfo(getComponentName());
   searchView.setSearchableInfo(info);
   return true;
}

You should understand most of it from my previous tutorial on ActionBarSherlock. New are the lines 6 to 11. These are where you add your search configuration to the SearchView.

As you can see in the code above, I use the SearchView together with ActionBarSherlock. ActionBarSherlock added a SearchView with its 4.2 release. As a deviation from ABS’ normal API level 7 support, the SearchView only work from API level 8 onwards. The reason for this is that the SearchableInfo interface was added with API level 8. So a support for a SearchView prior to that makes no sense.

The version in ActionBarSherlock’s 4.2 release had some problems with search suggestions. These were fixed by Matt Kranzler’s accepted pull request to ABS. But this fix is currently only available in the dev branch of ActionBarSherlock.

Update: With the 4.3 release of ActionBarSherlock suggestions now work. So if you want to use them, you have to include ActionBarSherlock 4.3 (or any follow-up releases).

The next screenshot shows the suggestions provider at work with ActionBarSherlock’s dev branch fixes on a 2.2 device:

Suggestions working in ActionBarSherlock when using the dev branch

Suggestions working in ActionBarSherlock when using the dev branch

Be very careful, if you use this branch. After all the current development is taking place here. It’s not yet finalized for production!

A custom ActionView

As mentioned you can also create arbitrary action views. You have some options to do so:

  • You can link to a layout file from within your menu.xml
  • You can set the layout when the action item is clicked
  • You can write a custom View implementation

I do not cover the last one. That’s because it’s the least likely solution for you and also because I haven’t yet covered how to create custom views in Android in this blog.

So let me show you how to use the first two.

Linking to a layout file

In this case you create a layout file and point to it directly from within your menu xml file:

<item 
   android:id="@+id/actionViewLayout"
   android:showAsAction="ifRoom|collapseActionView"
   android:icon="@drawable/ic_action_add"
   android:title="Add"
   android:actionLayout="@layout/activity_actionview_edittext"
/>

In line six you can see how the layout is referenced directly from within the menu item definition.

You still have the option to show it in expanded or in collapsed mode right from the outset. Line three in the xml snippet above uses a collapsed mode at first. The difference becomes obvious in the next screenshots. The first set shows the item in collapsed mode first. When you press the add item, Android expands the layout and moves all other action items into the overflow menu.

The add Actionview in collapsed mode

The add Actionview in collapsed mode


Add ActionView in expanded mode

Add ActionView in expanded mode

If you use the layout expanded all the time, it’s present all the time and takes up the place it needs. All other action items are visible – as long as some place is left for them. That’s what you see in the next screenshot. This option is the most space-constrained option you have. If your ActionView is always expanded, you probably have not much room left for any other action items. That’s the reason I use a landscape screenshot. So make sure you use the value ifRoom for the android:showAsAction attributes of all the other items – and to limit the action view to as little space as absolutely necessary.

ActionView expanded right away

ActionView expanded right away

To use the expanded view all the time you simply have to remove the collapseActionView value and the pipe symbol from line 3 of above’s xml snippet.

Of course it depends on the use case at hand and what your layout is, but I think this option generally is best used with an expanded layout all the time. Otherwise users might get confused by the disappearing action items when they expand the layout. And users might not know that they can use the back button to collapse the view again. If you plan to expand the layout on an action item click you’re probably better off with the option of the next paragraph.

Setting the layout when the user clicks the item

This option combines both methods of the former paragraph. Once again two screenshots demonstrate best what I am talking about:

Refresh ActionView in collapsed mode

Refresh ActionView in collapsed mode


Refresh icon replaced by ProgressBar spinner

Refresh icon replaced by ProgressBar spinner

The first screenshot shows the refresh icon as a normal action item. The layout file looks like any other menu item:

<item
   android:id="@+id/progress"
   android:icon="@drawable/ic_action_reload"
   android:showAsAction="ifRoom"
   android:title="@string/progress"
/>

But as soon as you click the refresh button, Android replaces it with the progress spinner. That’s because I set an action view in reaction to the action item click. The first code shows the onOptionsItemSelected() method in which I react to the item click:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   if (item.getItemId() == R.id.progress) {
      new DummyAsyncTask().execute((Void[])null);
      return true;
   }
   return super.onOptionsItemSelected(item);
}

The AsyncTask is a sample implementation showing you how to change the action view values:

private class DummyAsyncTask extends 
      AsyncTask<Void, Void, Void> {

   @Override
   protected Void doInBackground(Void... params) {
      // simulate doing some time-consuming stuff:
      SystemClock.sleep(2000);
      return null;
   }
   @Override
   protected void onPostExecute(Void result) {
      super.onPostExecute(result);
      ActionViewActivity.this.mProgress.setActionView(null);
   }   
   @Override
   protected void onPreExecute() {
      super.onPreExecute();
      ActionViewActivity.this.mProgress.
            setActionView(R.layout.activity_actionview_progress);
   }
}

As soon as the work is done and the new values have been downloaded, you simply set the action view to null again – in the code above I do this in the onPostExecute() method.

As you can see it uses an expanded mode – but only for the time, the user actually needs this view. Do not use the value collapseActionView in your menu item definition. Otherwise the layout expands on the left of the ActionBar and not in place of the icon!

Sample app

You can find the source of a sample app demonstrating all this on bitbucket. I’m more than happy if you spot any problems with the code and provide a pull request. You can also file an issue on the project page.

Lessons learned

In this tutorial you have seen how to make use of ActionViews. Very useful is the SearchView – thus I detailed how to add this to your ActionBar and how to link it to your search configuration in this post.

You have also seen that in the current 4.2 release of ActionBarSherlock SearchSuggestions are not yet working correctly. But thanks to a fix those will be part of the next ABS release.

Finally you learned how to create an ActionView on your own, though use cases for this are limited. Probably the most common one is replacing an update icon with the progress spinner widget.

Adding ActionBar Items From Within Your Fragments

This tutorial shows you how to add action items to the ActionBar from within your Fragments and how to disable or enable action items depending on the state of your fragment. All code works with the stock Android ActionBar object as well as with ActionBarSherlock.

Why do you want to add action items?

In a previous post you have seen that Android makes it easy to provide responsive interfaces. And given the vast distribution of devices sizes that is something you should do.

This post continues with the app, you have developed in the first posts of this series. The user has a list of items, a detail screen and an edit screen.

On a phone the startscreen simply shows a list of items. Here you have an action item to add a new item to the list:

Screen showing the ListFragment only

Screen showing the ListFragment only

The detail screen shows all the relevant details of this item and offers you to edit the item:

Screen showing the DetailFragment only

Screen showing the DetailFragment only

Now here’s what the tablet version looks like:

Top part of the tablet version containing both fragments

Top part of the tablet version containing both fragments

As you can see, it now sports both icons since it also presents both fragments. Now this app is pretty dull so far, and the detail screen even more so, so let me show you a real app. I take Timetable, an app that does this nicely.

Timetable app showing action items of multiple fragments

Timetable app showing action items of multiple fragments

In this screen the edit and trash icon are from the selected element and are only added when a lecture has been selected. The plus and the search icon though are from the ListFragment.

Adding action items programatically

As the post title implies the additional action items are inserted by the fragment. In fact not much different from how you add the items within your Activities. You use the onCreateOptionsMenu() method for it:

@Override
public void onCreateOptionsMenu(
      Menu menu, MenuInflater inflater) {
   inflater.inflate(R.menu.activity_itemdetail, menu);
}

As you can see the signature of this method is different from the one of the Activity class. With fragments your method takes a MenuInflater as second parameter. And the fragment’s onCreateOptionsMenu() method also doesn’t return a boolean value.

Even with this method in place Android still doesn’t display any additional menu items unless you explicitly tell it to call this method. To do so, you first have to call setHasOptionsMenu() within the fragment’s onCreate() method:

setHasOptionsMenu(true);

Now your fragments menu items will be displayed in the ActionBar.

Of course, if you do so, you have to stop using the same entries in your Activity. Otherwise it would look fine on any screen that makes use of your multi-pane layouts but you would end up with doubled icons on single-pane screens.

For the sample screen I have used a menu xml file containing only the about entry in the activity. And I use an xml file containing only the edit entry in the fragment. The about entry is not needed in the fragment, because it is added by the activity, no matter whether you are in single-pane or double-pane mode.

Changing the order of action items

By default Android displays the action items of your fragment behind those of the activity. If you use multiple fragments Android displays them in the order the fragments are created.

This default order is not necessarily what you want. For example it is very likely that you want to display an about item as the very last entry within your overflow-menu – no matter if fragments later on add more overflow-menu entries. Also some actions are more often used than others. You want to put them more to the left, so that, depending on the screen size, those are always visible. And which items are more important depends on which fragments are in use.

Tio help you achieve this you can make use of the android:orderInCategory attribute of the item elements.

The fragment_itemdetail.xml menu file:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
   <item
      android:id="@+id/edit_item"
      android:icon="@drawable/ic_action_edit"
      android:showAsAction="ifRoom"
      android:orderInCategory="10"
      android:title="@string/edit_item">
   </item>
</menu>

The activity_itemdetail.xml menu file:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
   <item
      android:id="@+id/about"
      android:icon="@drawable/ic_action_info"
      android:showAsAction="never"
      android:orderInCategory="9999"
      android:title="@string/about">
   </item>
</menu>

And finally the activity_itemlist.xml menu xml file:

<menu xmlns:android=
      "http://schemas.android.com/apk/res/android" >
   <item
      android:id="@+id/add_item"
      android:icon="@drawable/ic_action_add"
      android:orderInCategory="20"
      android:showAsAction="ifRoom"
      android:title="@string/add_item">
   </item>
   <item
      android:id="@+id/about"
      android:icon="@drawable/ic_action_info"
      android:showAsAction="never"
      android:orderInCategory="9999"
      android:title="@string/about">
   </item>
</menu>

The higher the number the later your action item is displayed. So use an absurdly high value for the about item. And order all other elements by importance.

Since all elements have an order value of zero by default, you have to use numbers for all action items as soon as you want to move one to the front.

android:orderInCategory="9999"

Handling events

As usual you can handle menu item clicks in the onOptionsItemSelected() method:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   // handle item selection
   switch (item.getItemId()) {
      case R.id.edit_item:
         // do s.th.
         return true;
      default:
         return super.onOptionsItemSelected(item);
   }
}

But bear in mind that the Activity’s onOptionsItemSelected() method is called first. Your fragment’s method is called only, when the Activity didn’t consume the event!

Adding and removing action items

So far I have only mentioned how to use action items, that are defined within an xml file. But that often is not sufficient.

See this screenshot of a German TV program app. Please ignore, that it’s in German, I explain what is relevant to you.

The Prime Guide app showing icons only when relevant

The Prime Guide app showing icons only when relevant

In this app you can select a program to get more information about it. If you select a program that hasn’t started yet, you can bookmark it and set an alarm for it. If on the other hand the program either has already started or ended those actions are not displayed. It simply makes no sense to add an alarm for some program that has already started. But all other icons are visible in both cases.

So how to do that? You could either use different menu xml files for a static set of action items. Or you could add or remove menu actions programatically. Since the second approach is more flexible I deal with it in the next paragraphs.

First you need to get hold of a Menu object. You can do so in the onCreateOptionsMenu() method shown above.

Now you can use this Menu object to either change the visibility of action items or to remove them from the menu entirely.

You can change the visibility like this:

if (mMenu != null) {
   mMenu.findItem(R.id.edit_item).setVisible(false);
}

The null check in the code is necessary, because of the order in which the methods of your fragment are called. Of course Android executes the lifecycle methods before finally calling onCreateOptionsMenu(). Thus your Menu object is null in the onCreateView() method, which you probably use to create event handlers.

If you want to entirely remove the action item, you can do so easily as well:

if (mMenu != null) {
   mMenu.removeItem(R.id.edit_item);
}

As you will see in the next few paragraphs, adding a menu item is slightly more cumbersome than just making it visible again. Thus if you want to toggle action items depending on the state of your fragment, I suggest to change the visibility instead of removing and re-adding the items.

So far I have only shown you how to get rid of action items. Of course you also can add new items. You can use one of the several add() methods of the Menu class. For example the following code fragment would add the item in the same way, as with the xml code for inflating it:

MenuItem item = 
      mMenu.add(Menu.NONE, R.id.edit_item, 10, R.string.edit_item);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
item.setIcon(R.drawable.ic_action_edit);

The first parameter sets the group. If you have no groups, use Menu.NONE. The second parameter sets the id you want to use. It’s the same one you later use in the onOptionsItemSelected() method to react to menu item clicks. The third parameter is the order value and the last one the title text you want to use. Remember, that Android uses the title text to display usage hints or to read out this value with a screenreader app. So never use null for this value.

As the code sample shows, you have to add the icon and the showAsAction attribute value with separate method calls later on.

I don’t know why there is no way to add a complete MenuItem object directly. To me that would be better readable. But that’s just a tiny detail :-)

Wrapping up

In this post I have shown that you can use the onCreateOptionsMenu() method to add action items related to your fragment to the existing icons of the ActionBar.

Since the default order in which Android adds these items is often not the preferred one, you can change this easily by adding the android:orderInCategory attribute to your menu items in the xml files.

Finally you have seen how to change the visibility of menu items, how to remove them completely or how to add new menu items.

Please let me know in the comments, if any questions are left open and which way you prefer to remove action items from the ActionBar. And don’t forget to plus one and share this post if you found it useful!

ActionBarSherlock: Up Navigation

In this tutorial I am going to cover some initial thoughts on navigation. The ActionBar allows multiple navigation modes. In this post I state which navigation modes exist, how to get to the ActionBar object in the first place and how to deal with the so-called up navigation.

Less code than in the previous parts because code-wise there is not much to it. But the concept is the cause for user confusion mostly caused by inconsistent implementations. I hope this post helps to get you on track to implement the up navigation in a correct way so that users understand your app easily.

Back and up navigation is a topic that’s always causing lot’s of discussions. When in doubt, please go to the developers community on Google+ or the user experience equivalent of StackOverflow and discuss the way you want to use it and if this is correct or not. If you have technical issues, though, please use StackOverflow.

The structure of the ActionBar

Let me go back for a second and explain the way the ActionBar is partitioned. I follow the terminology of the ActionBar pattern page in Android’s design guidelines here.

ActionBar of the detail screen on a 2.2 device

ActionBar of the detail screen on a 2.2 device

On the left side of the ActionBar is the app icon and possibly some indicator for the up navigation or the slide-out menu. Next comes the View control. This is often a text showing where you are. It could also contain tabs or a spinner as alternative means for navigating your app. Those elements are aligned to the left.

On the right side we have the action buttons followed by the action overflow – if an overflow menu is present.

What is important is to distinguish both areas. The left area is the part where you put navigational elements. Like moving up, tabs or a spinner. The right part is where you put actions that belong to the view. Like actions to add or delete elements, to update a list or for adding songs to your favorite lists.

I do not discuss those action items in this post. I have already described how to add action items and how to use the overflow menu. I probably cover the split ActionBar in another post and I will also deal with Action Providers and Action Views in a later post.

Navigation types of the ActionBar

Basically there are four types of navigation supported by the ActionBar pattern:

  • Go to the start screen of the app
  • Go up in the navigational hierarchy
  • Switch to another tab
  • Select another Spinner item

Accessing the ActionBar object

Before you can use any of the navigational modes, you need access to the ActionBar object, though. Since there is no public Javadoc page for the ActionBarSherlock library, I recommend to use the documentation of Android’s own ActionBar class, if you need to know about methods or fields of the ActionBar class. ActionBarSherlock’s class offers the exact same methods. Of course the signature is different since it uses ActionBarSherlock counterparts for any parameters or return values that use object of the ActionBar API – but should you migrate to ABS from a project that already makes use of the stock ActionBar, just changing the imports should suffice.

Using ActionBarSherlock you get the ActionBar object by calling getSupportActionBar() from within your SherlockActivity:

ActionBar actionBar = getSupportActionBar();

If your API target is at least API level 14 you could be tempted to use getActionBar() instead. After all this method appears first among the code-completion suggestions. But that won’t work on older devices – which is the reason to use ActionBarSherlock in the first place. So do the right thing and always call getSupportActionBar()!

Gladly Lint reminds you to do so:

Class requires API level 11 (current min is 7): android.app.ActionBar

But Lint cannot do so, when you added the Annotation SuppressLint("NewApi") to your code – so better be careful right from the beginning.

The method getSupportActionBar() is not available for fragments. But you can get access to the activity by calling getSherlockActivity(). And from here you can go on as shown above.

Be very careful here as well. If you call getActivity() instead, you will get an object of type android.support.v4.app.FragmentActivity. Since this class doesn’t have the getSupportActionBar() method you are even more prone to call the wrong method.

How does ActionBarSherlock’s ActionBar relate to Android’s ActionBar

ActionBarSherlock creates a wrapper to a native ActionBar object on all devices with an API level of at least 14 (ICS). And it creates a compatibility object for older devices. Both inherit from com.actionbarsherlock.app.ActionBar.

This is important to know. Because if you develop using an emulator or a device with a newer API level, you get away with being sloppy. Well, until you start to actually use an older device. When you start your app on an older device, your app will force close because of a NoSuchMethodError. Not too surprising, since the method getActionBar() was not available for Activities back then.

Navigating to the start screen

The ActionBar pattern has emerged before an official implementation existed. That’s the common way patterns emerge. The very first post on Juhani Lehtimäki’s excellent blog androiduipatterns.com shows some examples of apps that implemented the ActionBar in 2010. With the introduction of Honeycomb the Android team added the ActionBar to the API in 2011.

Back then it was all the rage to use the app icon as something akin to the home button or the logo on websites. It would get you immediately to the initial screen of the app. Of course back then it looked as if the dashboard would gain traction and so a click on the app icon would immediately bring you back to this hub. This all has changed, but you still could use the app icon that way.

But I advise not to use the home navigation model. Instead make use of the up navigation. Using the up model is the recommended pattern of Android’s design guidelines. I explain the up navigation in the next section. The code for home navigation would be nearly identical (it’s just another target Activity) – but you prefer to follow the guidelines anyway, don’t you?

Up navigation

With Ice Cream Sandwich the Android team has introduced the so-called up affordance to the platform. Perceived affordance is a visual clue helping users understand what a certain element does. In this case the up affordance helps the user to understand that he is going up (or back) a hierarchical level.

To be honest: I am still not convinced that this button is a useful addition to the Android platform, but that’s just me. In fact it’s a common pattern found in many current apps, it’s pushed by Google and it’s recommended on the design site. It looks like this pattern has established itself firmly. Thus, I recommend to use it, despite my misgivings!

So what is up navigation?

Up means getting up a hierarchy level. If you go up a level you usually also go back a level, thus the affordance, this tiny little left pointing caret, is not as weirdly chosen as it might sound.

Let me give you an example: Say you have a list of items and select one item. The detail screen would be the next hierarchical level. Up in this case would go back to the list of items. That’s what the app used in this series does so far. But apps often have multiple levels in their hierarchy. And using the up button can help users navigate the app faster – an important consideration in the mobile environment.

Before discussing this any further, let me first show you how to do this.

Adding the up affordance

Navigating within hierarchies means that the up affordance should be visible as soon as you navigate down one level. Which basically means that all screens after the initial screen of the app should sport the up affordance.

If you followed this series so far, you added the following lines to the ItemDetailActivity in the first part about using fragments and the support library:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   getActionBar().setDisplayHomeAsUpEnabled(true);
}

You had to add the if statement as a temporary workaround to make your project compile before you have added ActionBarSherlock to it. Remember that getActionBar() only works on newer devices.

Now that you have added ActionBarSherlock in the last post of this series, you can use getSupportActionBar() instead. And since this works on older devices as well, you can drop the if statement instead:

// Show the Up button in the action bar:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Reacting to an up click

When a user clicks on the home button of your app (not the home button of your device), you should navigate to the Activity that is logically one hierarchy above the current one. You do so within the onOptionsItemSelected() method of your ItemDetailActivity. In fact the Android developer tools did that already when you created the project:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
      case android.R.id.home:
         // This ID represents the Home or Up button. In the case of this
         // activity, the Up button is shown. Use NavUtils to allow users
         // to navigate up one level in the application structure. For
         // more details, see the Navigation pattern on Android Design:
         //
         // http://developer.android.com/design/patterns/navigation.html#up-vs-back
         //
         NavUtils.navigateUpTo(this,
               new Intent(this, ItemListActivity.class));
         return true;
   }
   return super.onOptionsItemSelected(item);
}

NavUtils’ navigateUpTo() method takes care of setting the flag FLAG_ACTIVITY_CLEAR_TOP and finishing the current activity. This flag ensures that a previous instance of this Activity within your task stack is reused, if available, and removes any activities on top of that activity.

Disabling the home button on the initial screen

Now when you already are at the root level of your app, there is no more up navigation possible. Thus you should disable the home button and the up affordance.

Doing so is simple. Just call setHomeButtonEnabled() and pass in a false value. For the project you have created in this series the home Activity is your ItemListActivity. Thus add this line to the onCreate() method somewhere after your call to the super method.:

// disable the home button and the up affordance:
getSupportActionBar().setHomeButtonEnabled(false);

So how is up different to the back button?

From what I have said so far, you might think that up is nothing else than the usual back button. But that’s not the case!

Both buttons can go back to the same screen, that’s true, but that’s not always the case.

Granted, for the app, you have developed so far in this mini-series, there is no difference between up and back. But most often you can get to a certain screen in your app in multiple ways. And that’s when back and up start to behave differently.

Up takes you always to a defined point of the app: The previous point in the hierarchy – no matter how you got to this point. Back though follows the trail you have chosen in reverse.

This is even more important if your app offers exported Activities for use by other applications. In this case the user might get to a screen of your app from an external app.

Up would still bring him up a hierarchical level within your app. Back on the other hand should bring the user back to where he came from – in this case the other app.

Even within your own app there can be differences. Say you are creating a conference app. From the schedule view the user selects one talk. The detail screen of the talk also links to other talks which are related as well as to talks that are by the same speaker. The user now might follow those links and thus view multiple talks. Now to return to the schedule fast, the user simply clicks the up icon and goes back to the schedule. With the back button though she would have to use multiple clicks – depending on the number of talks she has viewed.

Be wary of bad examples!

Don’t have a look at how other apps do it. Have a look at the design guide instead. There are way too many apps that do not behave correctly. There might be good reasons for doing so, but usually it adds to user confusion. It hurts the Android platform in general. Something you do not want to do, do you?

For example Google Play behaves incorrectly. You can go to the games category directly from the start screen. Or you can get there by going to apps and then selecting the games category. But up behaves differently, depending on where you came from. I can understand the reasoning behind it. They want to avoid confusion. But one level deeper the up button suddenly starts to work as up and not as back aynmore. What should users make of this?

As good-intentioned as this might be, I think it actually adds to the confusion. How should users grok the up button when it sometimes behaves incorrectly and works differently depending on where you are in the app? So, please, if you want to deviate from the guidelines, think twice. Think thrice. Discuss it with peers. Discuss it with usability experts. Do some users tests! Do your users and us all this favor!

What about the slide-out menu?

When discussing how to add the up affordance I said that you shouldn’t show an up affordance and that the home button shouldn’t be enabled when the user is on the initial screen of your app.

Obviously that’s not the case for the YouTube app, not for the Google+ app and an increasing number of other apps. YouTube as well as Google+ show the up affordance on the home screen and when you press the app icon again, the so-called slide-out menu appears. This is a relatively new pattern that has replaced the dashboard.

The slide-out menu has its name because it appears in a slide-out motion from the left side of the screen. It can be accessed using the up button – and sometimes by using a bezel-swipe from the left.

Keep in mind that this pattern is highly controversial. Jake Wharton, the creator of ActionBarSherlock, for example is a strong opponent of it. I personally like it, though I agree that it has some shortcomings. But with this in mind, carefully think whether your app needs one or not. Do not just add one, because it seems to be en-vogue right now. :-)

I won’t deal with this pattern here. There is a short paragraph on the ActionBar pattern page in the design guide. And you can find a detailed presentation of the slide-out navigation pattern on Juhani’s androiduipatterns.com site.

What you need to know is, that the trigger for this menu with regards to the ActionBar is also the up button. You react to it as described above. Of course you do not simply start a new Activity but have to show the menu instead. One library to help you do so is Jeremy Feinstein’s SlidingMenu library. Of course, there are others as well, but I happen to like this one.

Lessons learned

In this post you learned about the up navigation and how to implement it. You added the up affordance to one activity and disabled the home button on the other one.

You also learned what the difference between up and back is and how well-intentioned deviations from the standard can cause user confusion.

I didn’t cover how to properly deal with Widget or Notification clicks to your app. I am totally opposed to the recommended behavior and probably would rant too much. Well actually this might be a topic for another post so as to vent off a bit and explain why I don’t like it :-)   But not in this series.

I also left out how to create a new task and a simulated back stack when using the up button after a user got to your app from another app. I might do so in some other post if the need arises. But currently I think it’s explained sufficiently in the Android training class about ancestral navigation. The current app is too simple to explain this properly.

Has this post helped you? Do you have any more questions about up vs. back? Let me know about questions left open, any remarks you want to make or any mistakes you have spotted in the comment section.

Adding ActionBarSherlock to Your Project

In my last post I had a look at how to set up a Fragment project that uses a master detail view. This week I am going to show you the necessary steps to make this project use the ActionBarSherlock library.

ActionBarSherlock is a library by Jake Wharton, that enables you to use action bars even on older devices without having to code an action bar from scratch. This library deals with all the details you do not want to care about. Even Googlers like Roman Nurik or Nick Butcher recommend to use this library and the Google IO app also makes use of this lib. So should you!

With this post I start my series about the action bar by simply adding an action bar to the project of my last post, adding some action items to it and explaining some basics of action bars. The focus of this post is mainly on getting ActionBarSherlock to run on your project. As such it is an introductory post about the action bar.

Since the action bar offers many functions and is the most important navigational component Android has, more posts about it will follow in the next weeks.

Getting ActionBarSherlock and adding it to Eclipse

The first thing you have to do, is to download the library from actionbarsherlock.com. After this unzip/untar it. The download contains three folders: library, samples and website. The samples folder contains four sample projects to showcase what you can do and to show you how to do it. You should have a look at them. The website folder contains the code of the project website. The library folder finally contains ActionBarSherlock’s source code.

Now go to Eclipse and add the ABS-library as an Android project. Do not use Eclipse’s import tool to import the ActionBarSherlock library – it would not work immediately and you would have to fix some settings. Instead use the project creation wizard of the Android Developer Tools.

Open File -> New -> Project -> Android Project From Existing Code.

Creating an Adnroid project from existing source

Creating an Android project from existing source

In the next screen select the folder, which Eclipse then uses to search for projects. If you select the ActionBarSherlock root folder, Eclipse suggests a list of projects to create. Leave the “library” project checked and uncheck all others:

Select the library project

Select the library project

Click “Finish” to create the project.

Eclipse will now create a new project named “library”. I prefer a more useful name, so select the project called “library” and hit F2 to rename the project. I have renamed the project in Eclipse to “ActionBarSherlock”, so all following screens will refer to this name.

Adding the library to your project

Now that ABS is a library project you have to tell your own project to use it. I will use the project of my last post for this. Go to FragmentStarter’s project settings and switch to the Android tab.

If necessary scroll down until you see the Library panel. Click “Add”:

Adding libraries to an Android project

Adding libraries to an Android project

In the next window all available library projects will be listed. Select ActionBarSherlock and click “Ok”.

Select ActionBarSherlock from the list of libraries

Select ActionBarSherlock from the list of libraries

When the window disappears the library should be listed in the library panel of the Android properties tab:

Check if the library has been added succesfully

Check if the library has been added succesfully

What is slightly annoying is that the Android Developer Tools do not use the name of a project to reference it, but instead point to the directory itself. And what’s even more annoying is that a symlink gets translated to its real path, which is bound to change more often than a symlink.

Should you ever want to change the directory, you have to delete the reference to the library with the old path and link to the newly imported library. But unless you do a fresh install for blog posts, this probably won’t happen too often :-)

That’s it. Your project bundles the lib from now on.

But wait a moment! If you have a look at your project, you will notice that it now sports a red warning icon. Go to the error tab and you will see lots of warnings. Eclipse states for Fragment, FragmentActivity and all the other classes of the support library, that they “cannot be resolved to a type”. Whoops!

Unknow type problems after adding ActionBarSherlock

Unknow type problems after adding ActionBarSherlock

The reason is, that ActionBarSherlock comes bundled with the library as well. And most of the time the support library added when following my post about fragments is different from the one bundled with ActionBarSherlock. In the console tab of Eclipse you see the message “Jar mismatch! Fix your dependencies” with the hashcodes of the mismatching files and where these files are stored:

[FragmentStarterProject] Found 2 versions of android-support-v4.jar in the dependency list,
[FragmentStarterProject] but not all the versions are identical (check is based on SHA-1 only at this time).
[FragmentStarterProject] All versions of the libraries must be the same at this time.
[FragmentStarterProject] Versions found are:
[FragmentStarterProject] Path: /opt/workspace/FragmentStarterProject/libs/android-support-v4.jar
[FragmentStarterProject] 	Length: 385685
[FragmentStarterProject] 	SHA-1: 48c94ae70fa65718b382098237806a5909bb096e
[FragmentStarterProject] Path: /opt/libs/ActionBarSherlock/library/libs/android-support-v4.jar
[FragmentStarterProject] 	Length: 349252
[FragmentStarterProject] 	SHA-1: 612846c9857077a039b533718f72db3bc041d389
[FragmentStarterProject] Jar mismatch! Fix your dependencies

To fix this, simply delete the support library from you project. Go to the libs folder, select the android-support-v4.jar file and delete it. You can still use the support library because it’s also part of the ABS project.

If you need a newer version of the support library than the one bundled with ActionBarSherlock, remove the support library from both projects and add it anew to the ActionBarSherlock project.

With this done your project is good again. The next step, of course, is to change some code.

Changing the types to their ActionBarSherlock counterparts

Just adding the library won’t magically add an action bar to your project. Instead you have to change some of your code.

The first thing you have to do, is to change the classes from which you inherit. Instead of Activity use SherlockActivity, instead of FragmentActivity use SherlockFragmentActivity, instead of Fragment use SherlockFragment and so on. Now do this for the two activities and the two fragments you created while reading the last post.

You will notice that the ItemDetailActivity won’t compile any more. Whenever you add ActionBarSherlock to an existing project, this is bound to happen. Why is that?

Have a look at the error message Eclipse is displaying: “Cannot override the final method from SherlockFragmentActivity“. The method is the following:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   // ...
}

ActionBarSherlock overrides every method of it’s superclasses that takes either a Menu, MenuItem or MenuInflater object of the android.view package as parameter and declares those methods as final. You need to know that all the items in an action bar are actually menu items. Thus only by doing it this way ActionBarSherlock can take control of all the menu-handling and change it for older Android versions.

While the error message might sound bad, it actually isn’t. ActionBarSherlock provides
for every final method another method with the same name and the same number of arguments. Even the class names of the arguments are the same. Only the packages differ.

This way ActionBarSherlock makes migration of existing projects very easy. You can keep your methods and do not have to change and adjust any logic. Simply delete all import statements to the menu-related classes of the package android.view. After this hit Ctrl-O to optimize and correct the import statements and when Eclipse displays the list of imports to choose from, choose those of the ActionBarSherlock library:

Choose ActionBarSherlock's classes for imports

Choose ActionBarSherlock’s classes for imports

If you do this for ItemDetailActivity the warnings disappear. Whenever you use Eclipse (or any other IDE for that matter) to generate the import statements for you, take care to select the types of the ActionBarSherlock library. Those all start with com.actionbarsherlock.

Now that your code looks fine, you should try to run the project. Whether this run is successful or not depends on the Android version of your device. If you run this code on a device with at least Android 4.0 everything runs fine. But not so on older devices. Here you will get a Force Close dialog due to an IllegalStateException:

java.lang.IllegalStateException: 
      You must use Theme.Sherlock, 
      Theme.Sherlock.Light, 
      Theme.Sherlock.Light.DarkActionBar, 
      or a derivative.

Gladly the exception is pretty specific: You have to use one of the Sherlock themes to get your project to run. ActionBarSherlock needs many definitions to get the action bar styled correctly. Thus it needs these styles and you have to use the ABS themes. You can use your own theme, of course, but you must use one of Sherlock’s themes as a base for yours. See the Sherlock theming guide for more information on this.

Since adding the action bar to older devices is the reason to use ActionBarSherlock in the first place, you have to change the theme. Change your AndroidManifest.xml file to use a Sherlock theme:

<application
   android:allowBackup="true"
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name"
   android:theme="@style/Theme.Sherlock.Light" >
   <!-- ... -->
</application>

Now finally the app runs fine. And yes, there is an ActionBar. As you can see it works fine on current as well as on older devices:

Initial action bar on a 2.1 device

Initial action bar on a 2.1 device


Initial action bar on a 4.2 device

Initial action bar on a 4.2 device

Adding items to the ActionBar

The action bar is basically what the old menu was before Honeycomb. This means that you have to create a menu to see an action bar.

Create a file with the name activity_itemlist.xml in the folder /res/menu and add the following code to it. This file describes the structure of your action bar:

<menu xmlns:android=
      "http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/add_item"
        android:icon="@drawable/ic_action_add"
        android:showAsAction="ifRoom"
        android:title="@string/add_item"
        android:titleCondensed="@string/add_item">
    </item>
    <item
        android:id="@+id/about"
        android:icon="@drawable/ic_action_info"
        android:showAsAction="never"
        android:title="@string/about"
        android:titleCondensed="@string/about">
    </item>

</menu>

Note: I use icons from the icon pack “Android Developer Icons 2″ of opoloo. The values I use for the android:icon attributes are specific to this icon pack. As soon as you want to try this code, you have to prepare icons that match this code or change the attribute value to fit your icons. See the appendix for more on this.

Only the xml file won’t suffice. You also need to override the onCreateOptionsMenu() method to inflate this file:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getSupportMenuInflater();
   inflater.inflate(R.menu.activity_itemlist, menu);
   return true;
}

This is the result when you run the project again. Note the differences between the 2.1 device and the 4.2 device:

Action bar with icons running on a 2.1 device

Action bar with icons running on a 2.1 device after pressing the menu button


Action bar with icons running on a 4.2 device

Action bar with icons running on a 4.2 device

The overflow menu

When you compare the screenshots of the previous section, you quickly understand what the so-called overflow menu is. This is the menu hidden behind the three dots are the far end of the action bar on modern devices.

Android shows as many items as it can directly on the action bar. But especially on phones the place for action items is quite limited. Thus Android shows all those items, that do not fit on the action bar directly, in the overflow menu. You can also tell Android to put items in the overflow menu regardless of the space. You can do so by using the value never for the attribute android:showAsAction of these items. More on this attribute later on.

The items of the overflow menu are only visible if you click the three dots on the right of the action bar or press the menu button on those devices that have such a button.

The three dots appear only on devices without a menu button. That’s the way to indicate to the user that more items are available and it’s also the only way how users can access these items. On devices with a menu button on the other hand you do not have any indicator, but users can always check if an overflow menu is present by clicking the menu key. I actually think the solution for devices without menu button is way better than the solution on devices with a menu button. On these latter devices users always have to guess if an overflow menu is present or not. Alas Samsung, the vendor that sells by far the most Android devices, still ships devices with menu buttons :-(

Sort your items by importance so that the most important actions are visible all the time. Those actions are the ones your users are most likely to perform on this screen. Think thoroughly about the importance of each item.

Other items should always be in the overflow menu, no matter how much space is left. For example if your app has an about screen, or some license info for the open source libs you use (well, ActionBarSherlock for example) or some information about what has changed with the recent version, I would put all those items into the overflow menu – no matter how much screen estate you have left.

The Android design page has some more guidance on this on their action bar pattern page and also shows you roughly how many items fit on the screen for some selected devices.

Use the android:icon as well as the android:title attribute

As you can see the action bar shows only an icon for the “Add Items” action. But that doesn’t mean that you should neglect the strings. First of all these strings are used for screenreaders so that visually impaired people still can use your app. And secondly, if users do not understand an icon immediately, they can longpress those icons until a hint appears that displays the text. Of course this hint is no excuse for confusing icons!

Another thing to note. Overflow menu items show only text. But not so on older devices. There you see the icon and the text. So always provide values for android:icon and for android:title!

Use android:showAsAction to define the appearance of the action items

The item element of the xml file for the action bar can contain four attributes that are only relevant for the action bar: android:showAsAction, android:actionLayout, android:actionViewClass and android:actionProviderClass. Of these I describe only the frst here, the other three are a topic for an extra post.

You can use the attribute android:showAsAction to decide which icons to display and in which way. It can take the following five values:

Possible values for the android:showAsAction attribute
Value Meaning
ifRoom Display item if enough room is left for this item
always Display this item, regardless of the existing place
never This item is not displayed in the action bar directly but in the overflow menu
withText Display the icon together with the title text
collapseActionView Only relevant for collabsible action views – not covered in this post

As a rule of thumb you should always use ifRoom, if you want the icon to be part of your action bar and you should use never if you want the item to always be part of the overflow menu.

The Android documentation for menu resources explicitly urges you to use always with great care. You should use this attribute only if the element is absolutely necessary. If you use this on multiple items and the place in the action bar is too small to do this properly Android displays overlapping icons. In this case the items are even less accessible than those of the overflow menu.

While you have to pick one of the first three, you can combine these with the value withText. This value decides whether Android shows only the icon or the icon plus the text of the android:title attribute. But Android does show the text only, if enough room is left.

As an example change the menu file to the following code:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
   <item
      android:id="@+id/add_item"
      android:icon="@drawable/ic_action_add"
      android:showAsAction="ifRoom|withText"
      android:title="@string/add_item">
   </item>
   <item
      android:id="@+id/reload_list"
      android:icon="@drawable/ic_action_reload"
      android:showAsAction="ifRoom|withText"
      android:title="@string/reload_list">
   </item>
   <item
      android:id="@+id/about"
      android:icon="@drawable/ic_action_info"
      android:showAsAction="never"
      android:title="@string/about">
   </item>
</menu>

Now these are the resulting screens depending on the Android version:

Action bar with multiple icons running on a 2.1 device

Action bar with multiple icons running on a 2.1 device


Action bar with multiple icons running on a 4.2 device

Action bar with multiple icons running on a 4.2 device after selecting the overflow menu

As you can see on phones Android still only displays the icons. Note what happens on small devices that have no menu button. Android had to put the second item into the overflow menu because it had not enough place for it. On devices with a menu button the second item would be directly visible in the action bar.

This is what the same app looks like on a tablet:

Action bar with multiple icons and text running on a 4.2 tablet

Action bar with multiple icons and text running on a 4.2 tablet

Now the withText value makes a difference. While I like items to display text on tablets, it is very unusual. Have a look at other apps to see how they do it, before you decide whether to display text or not. But do not use text to gloss over weaknesses in your icon design.

Dealing with user input

So far you have created the action bar and made it look right. But when you click on an item, nothing happens.

What you have to do is to implement the onOptionsItemSelected() method. You do this as you always did for menu item selections:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
   // Handle item selection
   switch (item.getItemId()) {
      case R.id.add_item:
         // do s.th.
         return true;
      case R.id.about:
         // do s.th.
         return true;
      default:
         return super.onOptionsItemSelected(item);
   }
}

Action bar interaction is like any other user interaction and all the usual rules about the UI thread apply. So don’t put any stuff in here that’s long-lasting. Use Loaders, AsyncTasks, IntentServices or whatever you prefer for the specific job to do the heavy lifting.

What’s next?

In this first part of the ActionBar tutorial you have changed your project so that your activities and fragments now inherit from ActionBarSherlock’s classes and then made it compile and run.

After this you added items to the action bar, learned about the overflow menu and about the ActionBar-related attributes of the menu xml files. But with this you barely scratched the surface of what the action bar covers.

According to the design guidelines the “action bar is one of the most important design elements you can implement”. No wonder it features all sorts of possibilities. And, yes, it brings with it some complexity as well. So there is more to the action bar than just this post.

In the next post I am goig to cover the different navigation types the action bar supports. After this I will write yet another post about the so-called contextual action bar.


Appendix

As mentioned all icons that I use are icons of opoloo’s Android Developers Icons 2. You have to either get this pack, create icons for yourself or download the “Action Bar Icon Pack” from the design site. The latter icon pack contains no “Add” icon, so you have to adapt the XML.

You can also use totally inappropriate icons and hassle with the design later on. For the sake of following this tutorial you could use something like @android:drawable/ic_menu_add. But you should never use these for anything else than for just getting on with this tutorial.

You have to add the icons you want to use to the respective folders within your /res folder. For details on how to name these folders see the Android documentation about providing resources.

Getting Started With Fragments and the Support Library

Fragments are modular building blocks for creating a responsive Android UI. They help you to target different devices and screen sizes while at the same time avoiding code duplication.

This post starts with the Android Developers Tools generating a project for you. I then explain some of the generated code and will show you how to make this code work on older devices. To do this kind of post was suggested by a user of a German forum. Let’s see if this works well.

This project will grow over time. In the next post I will add the ActionBarSherlock library to the project – but this time it’s all about understanding the basics.

This post is not taking the approach, Martin van Z or Sebastian Kaspari are taking with their respective series “Creating your own Android app” and “Instant Moustache“. They cover planning stages, sketching and the like as well. Both series make for very interesting reading!

The basics of fragments

Fragments constitute a part of your Activity you present to the user. Most often they are used to display some section of the screen and to react to events that happen within this section. Fragments are modular, come with their own lifecycle and help you to avoid code duplication.

Fragments come in two varieties. Either the normal Fragment class within the android.app package that was introduced with API level 11 (Honeycomb). And the support library Fragment of the package android.support.v4.app. Both have subclasses like DialogFragment or ListFragment. You cannot use a mix of normal and support libary fragments.

If you want to target older devices in your project, always go for the classes of the support library. If you only care about newer Android releases, you can use the normal fragments.

In this post I specifically have a look at how to make fragments work with the support library. Given the vast amount of Android 2.2 and 2.3 devices currently out there I still recommend to always try to target these devices where possible. And since the differences in the Android framework between Android 2.1, 2.2 and 2.3 are not too big, I suggest to try with 2.1 and only increase the minimum API level if you have a need for this.

Fragments have a UI on their own. As usual you inflate your view, which you have defined in XML files. While Fragments without any UI are possible, I won’t cover those in this post.

View creation is nothing special. Apart from one thing. If you use the android:onClick attribute for your view elements, you cannot implement the method in the fragment. You have to implement it in the activity. If you want to deal with click events in your fragment you have to add OnClickListeners for those view elements programmatically.

Fragments have a lifecycle of their own. It is a bit more complex than those of Activities, because Fragments can be attached to and detached from their enclosing activities. I will cover some of the lifecycle methods below.

So much for the background on fragments. If you want to learn more, head over to Google’s documentation about Fragments after reading this post.

In the next section I start by creating the project using Android’s Developer Tools.

Creating the project using the Android Developer Tools

To follow the steps outlined here you must have Eclipse together with the Android Developer Tools plugins installed. You can download complete bundles on Android’s SDK page.

In Eclipse go to File -> New Project -> Android Application Project and click “Next”. A wizard pops up:

Android Developer Tools project wizard

Android Developer Tools project wizard

Fill in the required fields as shown above and click next until you come to the screen where you can select the type of project you want to create:

Project wizard for master detail projects

Project wizard for master detail projects. Note the API level warning.

Select the master detail project type. That means that you have a list of elements on the left and a detail view on the right – if your screen is big enough.

As you can see the API level we have chosen isn’t supported. So go back to the beginning and switch to API level 11. You will correct this later on:

Switch to API level 11 in the project wizard

Switch to API level 11 in the project wizard

Now go on until you come to the screen showing the name for the entities you want to deal with:

Select an enity name in the wizard

Select an enity name in the wizard

Item is the default here. I do not bother to change this, but you can change it to whatever your app is going to deal with – like Book, File and so on. Keep in mind that the wizard creates the names of the classes accordingly. So whenever I refer to Item, ItemListFragment and so on, substitute Item with the noun you have chosen in this dialog.

Now click Finish and the Eclipse generates the project for you.

If you never have downloaded the support library and do not use the adt bundle, the following dialog will pop up. It forces you to download the library and attaches it to your project:

The wizard alerts you that the support library is missing

The wizard alerts you that the support library is missing

Fragments lifecycle

I do not cover the entire lifycycle of Fragments. Much of it is comparable to the lifecycle of Activities. But by having a look at the code, I will show some common lifecycle methods you should know about.

First, have a look at ItemDetailFragment. This fragment inflates a view. But it does not do so in the onCreate() method like you would do in an activity, but within the onCreateView() method. Android passes the inflater you need to use for view inflation into the method, as well as the container for your view.

The inflation always looks like this:

View rootView = inflater.inflate(
      R.layout.fragment_item_detail,
      container, false);

The last parameter states that your view should not be attached to the container. It must always be false for fragment view inflation. Android adds your view to the container itself!

Since fragments can be attached or detached from an activity, there also exist onAttach() and onDetach() methods. After your fragment has been attached, you can use getActivity() within your fragment to get to the enclosing activity.

The ItemListFragment makes use of both methods to set a callback interface. I explain this interface in the next section.

The other lifecycle methods are the same as for activities. You can read more about the lifecycle in Android’s documentation.

Callback interface

Fragments and activities need to communicate with each other. But you do not want to couple them closely. Your fragment might end up in multiple activities, so it should never have a direct link back to the activity it belongs to. Instead it is common practice to use interfaces to deal with this. Your fragments define callback interfaces and your Activities must implement these interfaces.

Have a look at the ItemListFragment. It contains the interface named Callbacks. The fragment uses this interface to communicate to the activity that an item has been selected:

public interface Callbacks {
   /**
    * Callback for when an item has been selected.
    */
   public void onItemSelected(String id);
}

This interface is used in the onListItemClick() method:

@Override
public void onListItemClick(ListView listView, View view, int position,
      long id) {
   super.onListItemClick(listView, view, position, id);
   
   // Notify the active callbacks interface (the activity, if the
   // fragment is attached to one) that an item has been selected.
   mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
}

See also the methods onAttach() and onDetach(). That’s where the internal member mCallbacks is set to the enclosing activity or to a dummy implementation, if this fragment is no longer part of an activity.

The ItemListActivity implements this interface. So look at the activity’s onItemSelected() method. It first checks if you are in dual pane or single pane mode (see next section). And depending on the result it either starts another activity or replaces the second fragment.

When you have many callbacks and multiple fragments using interfaces for every fragment can become pretty unwieldy. In this case I recommend to use a bus based approach like EventBus or Otto. But that’s a topic for another post. At the current state of the project the interface approach works fine.

Dual pane or not

The most important reason to use fragments is to make your app responsive. That means make it adapt nicely to a change in orientation and to different screen sizes and aspect ratios.

The generated project shows this by using two panes on tablets and a single pane on phones. It defines two layouts for the ItemListActivity in the layout folder: activity_item_list.xml and activity_item_twopane.xml.

The files in the layout folder

The files in the layout folder

Wait a moment. Two layouts for the same activity with different names and both in the default layout folder? What’s up with that?

Well have a look at the values folders in the res directory:

The different values folders

The different values folders

Of interest in this case are the values-large and the values-sw600dp folders. Both contain a file named refs.xml which references the activity_item_twopane.xml file:

<resources>
   <!--
   Layout alias to replace the single-pane version of the layout with a
   two-pane version on Large screens.
   
   For more on layout aliases, see:

http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters

   -->
   <item name="activity_item_list" type="layout">@layout/activity_item_twopane</item>
</resources>

Note the name attribute of the reference. Its value is activity_item_list. This means that when you use R.layout.activity_item_list in your code, Android will replace this value with R.layout.activity_item_twopane. Of course only if one of the two qualifiers large or sw600dp applies. That way you have to declare the layout only once and can refer to it in multiple places.

You have to use the large qualifier even though a more specific qualifier is present, because the swXYZdp qualifier will only be recognized from API level 13 onwards. Prior to this only the screen qualifiers folders (small, normal, large and xlarge) have been recognized.

If you look at the activity_item_twopane.xml file, you will see that a fragment and a FrameLayout is declared.

You can declare fragments either directly in your layout files or you can use FragmentTransactions to add fragments programmatically. In this case one fragment is added using the xml file while the other is added using a transaction. The FrameLayout within this file is the container that you later add the fragment to in your transaction.

In the ItemListActivity you finally find this code snippet:

if (findViewById(R.id.item_detail_container) != null) {
   // The detail container view will be present only in the
   // large-screen layouts (res/values-large and
   // res/values-sw600dp). If this view is present, then the
   // activity should be in two-pane mode.
   mTwoPane = true;
   
   //...
}

So by either finding this container or not, the activity knows whether Android selected the two pane layout or not.

Depending on this, the activity handles a list item click differently in the onItemSelected() callback method.

There is also another approach used on some of Google’s Android training pages and mentioned by Kiran Rao in the comment section. The other approach uses a boolean variable in xml files. Have a look at Kiran’s comment to learn more about this approach.

You should really dig deeper into how to deal with multiple screen sizes. It is a very important concept for supporting multiple device sizes in Android. Thus I recommend you take the training about multiple screensizes on the Android site after reading this post. Do not write apps for phones only. As has just been published, the tablet market for Android is gaining serious traction. Don’t miss out on this. And don’t risk bad ratings just because you ignored bigger screens!

FragmentTransactions

FragmentTransactions are Android’s way of adding, removing, hiding or replacing fragments to or from your activity. As the name transaction implies either all actions of the transaction are done or none. So you transfer from one valid state of your app to another one.

But you not only manage the fragments themself, you can also define custom animations to display for fragments being attached and detached.

And you can add a complete transaction to your backstack. In this case clicking back would do everything within the transaction in exactly the reverse order. If you do not use the addToBackStack() method to add your transaction to the backstack, this transaction will be ignored. You can see this in the sample app in two pane mode. Clicking on different list items starts a transaction and causes a replacement of fragments. But by clicking back you just leave the app. Which makes sense, since you do not want every list item click to be added to the back stack.

I have covered here just some basics of FragmentTransactions. To learn more about them, visit Daniel Lew’s blog post about FragmentTransactions.

Make it run on older devices

The code was generated by the wizard for API level 11. But it uses the support library already – so shouldn’t it run on older versions as well?

The heavy lifting already has been done. The wizard created both activities as subclasses of FragmentActivity. This is a class of the support library that allows you to access an FragmentManager using getSupportFragmentManager().

Two changes are needed to make it run on older versions.

First the generated class ItemListFragment contains a layout constant that has been introduced in API level 11: simple_list_item_activated_1. This specific layout highlights activated list items. Which is useful, if you have a multi-pane layout, because it shows the user which list item is selected and displayed in the details pane.

I ignore the highlighting for now and just try to get the code to run:

int layout = android.R.layout.simple_list_item_1;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   layout = android.R.layout.simple_list_item_activated_1;
}
setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(
      getActivity(),
      layout,
      android.R.id.text1, 
      DummyContent.ITEMS));

The second problem is the ActionBar, which is not available on older devices without adding an additional library. Since this is the topic of my next post, I simply ignore the ActionBar on older devices for now. Change the line with getActionBar() to this in the ItemDetailActivity:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   getActionBar().setDisplayHomeAsUpEnabled(true);
}

Now you get a Lint warning. That the call requires API level 11 but that your manifest file states API level 7 as a minimum. Add an annotation to suppress the new API warnings for the onCreate() method:

@SuppressLint("NewApi")

Now change your AndroidManifest.xml file to support API level 7:

<uses-sdk
   android:minSdkVersion="7"
   android:targetSdkVersion="16" />

With these changes, you can now run the project on older devices.

Lessons learned

You have seen how to create a master detail project using the Android Developer Tools and how the generated project works.

I have given you details about what fragements are and what to use them for. And I have shown you some code snippets of the generated project and explained why it is done that way.

Also I have shown to you how to make this project backwards compatible. That way you can run the code on older devices as well.

Keep in mind: The Android Developer Tools project is evolving at a rapid pace. So if you read this post in a few months some of this probably has changed – though the basics should remain the same.

I strongly recommend to keep an eye on updates to the developer tools. Check for updates in Eclipse regularly.

And if you want to know of what’s to come, visit the project page of the ADT team and especially their announcements of recent changes. The team announces preview versions there on a regular basis.

Next week you will add an ActionBar using the library ActionbarSherlock to your project. Until then have a good look at the code and jump to Android’s training session about fragments to learn more. Fragments are very important and it is essential to fully understand them!

Android: How to Use Two Data Sources in ListViews?

Sometimes in our apps we have the need to link to data of other sources. You have a database of your own for your app, but some records also point to the MediaStore content provider to calendar entries or to contacts.

For all detail pages this is not much of a problem. You get the data from your database and query the external content provider for additional data based on the id or lookup uri that you stored in your database.

But what to do, if you want to show data in ListViews? Say contact pictures, event titles for multiline list elements and so on. Then it gets complicated.

From what I see, we have the following choices. Neither is fully satisfying – which is why I would like to hear how you deal with these kind of problems.

  • You get a list of all elements of the ListView by querying your database. And you query the content provider for each list entry using an AsyncTask. This is the a very memory efficient solution.

    For images (album covers, contact pictures…) this is probably the best option. Especially if combined with an in-memory cache. Even if users would love to see images immediately, they know this is not feasible and accept some lag before images are displayed.

    But not so for any text elements. The second line of a multiline list element should be visible instantaneously. So for text this option is not acceptable.

  • You could query the content provider for all entries at startup, put them in a HashMap and use this map later on. Well this might work if the content provider has only a few entries. But there might be thousands of media files on a SD card or thousands of contacts for a big company. In cases like these this won’t work. It would be a big waste of memory – especially since you probably only need very few of these rows at all.

    The Hashmap would also need too long to be created in the first place. The waiting period for the inital screen would be inacceptable. So this is basically a no-go.

  • You could keep redundant data in your own database. For every record that contains a link to the external content provider you also include the data, you need in the listview (e.g. the band name). That’s the option I have chosen. You only cache the results you actually need.

    There are two drawbacks to this solution: First you are wasting device memory. That is flash memory not RAM. No problem for most high end devices but low cost devices often have very limited memory available.

    Second you have to sync the data whenever your app restarts. If your app stays in the background for quite a while, the user might have changed the external data source. In fact this might even happen while your app is in the foreground if a sync adapter changes values based on changes of the backend. Now your list reflects the wrong values until your database has re-synced with the external provider.

    You could choose to listen to changes in the content provider in a service and update your database when needed. Activities then could query for changes.

    Whether these two issues of this option pose problems for you depend on the type of app. In most cases a correction of a changed value later on should be okay. And if you do not have hundreds or thousands of rows in your own table the inefficiencies are not that bad as well.

Now I would really like to hear what you think. Probably there are other options, I have overlooked. Or better ways to make one of these three options work. Please let me know in the comments, on G+ or on Twitter. Thanks!

If you are curious about the G+ discussion, have a look at my G+ announcement of this post.

Use Android’s ContentObserver in Your Code to Listen to Data Changes

When you are using a content provider as a client, chances are that you want to know whenever the data changes. That’s what Android’s class ContentObserver is for.

To use the ContentObserver you have to take two steps:

  • Implement a subclass of ContentObserver
  • Register your content observer to listen for changes

Implement a subclass of ContentObserver

ContentObserver is an abstract class with no abstract methods. Its two onChange() methods are implemented without any logic. And since these are called whenever a change occurs, you have to override them.

Since Google added one of the two overloaded onChange() methods as recently as API-level 16, this method’s default behavior is to call the other, older method.

Here is, what a normal implementation would look like:

@SuppressLint(&quot;NewApi&quot;)
class MyObserver extends ContentObserver {		
   public MyObserver(Handler handler) {
      super(handler);			
   }

   @Override
   public void onChange(boolean selfChange) {
      this.onChange(selfChange, null);
   }		

   @Override
   public void onChange(boolean selfChange, Uri uri) {
      // do s.th.
      // depending on the handler you might be on the UI
      // thread, so be cautious!
   }		
}

Some things are important with the above code. The first thing you must know, is that the second method is only available from API level 16 onwards. That’s why I added the SuppressLint annotation. The code works fine on older devices, but in this case Android obviously always calls the old one. So your code should not rely on a URI to work properly.

Also notice the Handler parameter in the constructor. This handler is used to deliver the onChange() method. So if you created the Handler on the UI thread, the onChange() method will be called on the UI thread as well. In this case avoid querying the ContentProvider in this method. Instead use an AsyncTask or a Loader.

If you pass a null value to the constructor, Android calls the onChange() method immediately – regardless of the current thread used. I think it’s best to always use a handler when creating the ContentObserver object.

Register your content observer to listen for changes

To register your ContentObserver subclass you simply have to call the ContentResolver's registerContentObserver() method:

getContentResolver().
      registerContentObserver(
            SOME_URI, 
            true, 
            yourObserver);

It takes three parameters. The first is the URI to listen to. I cover the URI in more detail in the next section.

The second parameter indicates whether all changes to URIs that start with the given URI should trigger a method call or just changes to exactly this one URI. This can be handy for say the ContactsContract URI with its many descendants. But it can also be detrimental in that the actual change, that caused the method call, is even more obscure to you.

The third parameter is an instance of your ContentObserver implementation.

The URIs you can observe

As described in my introduction to content providers content URIs can be directory-based or id-based.

Both of these URI-types can be used for your content observer. If you have a detail screen you would use an id-based URI for your observer, and when you use a list of data a directory-based URI is more appropriate.

This does not always work, though. ContactsContract for example always triggers a change, whenever any contact was changed, even if you are listening to a more specific URI. It depends on the correct implementation of the content provider. I have filed a bug report for the ContactsContract provider. Please vote for this issue, if you agree.

When you write a content provider for your app, take care of notifying the correct URI. Only if you do so, the feedback mechanism described here works. This is important for your observers – or if the provider is exported for your clients’ observers as well. And it is also important for Loaders. See my post about how to write content providers to learn more about this.

Note: If you use Loaders you do not need to listen to changes yourself. In this case Android registers a ContentObserver and triggers your LoaderCallbacks onLoadFinished() method for any changes.

Do not forget to unregister your content observer

When you have registered a content observer, it is your responsibility to also unregister it. Otherwise you would create a memory leak and your Activity would never be garbage collected.

To unregister you call the unregisterContentObserver() method of the ContentResolver:

getContentResolver().
      unregisterContentObserver(yourObserver);

You register your observer in the onResume() lifecycle method and you unregister it in the onPause() method.

This is not relevant to ContentObservers alone but applies to everything you register. As a general rule of thumb: Whenever you start coding registerXYZ() immediately also add the code to unregisterXYZ(). Otherwise you might later forget about it and inadvertently create memory leaks.

Sometimes you wish you would know more about the changes

The main downside with content observers is, that you do not get any additional information about what has changed. For directory-based URIs it would be nice to get a list of IDs that have changed. Some providers can have many records and re-reading all records, if only a few have changed, is a waste of resources in a mobile environment. Also some hint of the type of change would be nice. Like if a record was deleted or inserted.

The ContentProvider responsible for the change knows all this. So this would be no problem to add. Of course it has to be added in a backwards-compatible way.

API level 16 added a URI to the onChange() method, but this isn’t sufficient for updates of multiple records and also doesn’t tell you anything about the type of change.

Wrapping up

This quick tip showed you how to leverage Android’s ContentObserver. This makes it easy to react to updates of the data you are using.

As you have seen, it is pretty easy to implement the ContentObserver subclass. You have also seen that you can register it to listen to id-based as well as directory-based URIs.

Of course this works only, if the content provider for the URI you are observing, is correctly implemented and notifies clients of changes. If you are implementing a content provider yourself, have a look at my tutorial on writing a content provider for how to do so.

What You Need to Know About the Intents of Android’s Calendar App

When your app needs to access calendar data you have to choose whether to use the CalendarContract content provider or whether to use Intents to start specific Activities of the Calendar app. This post covers the intents offered by the official Calendar app.

While with using Intents your possibilities are limited compared to those of the content provider, using intents has the advantage that the user already knows the Calendar app and that some things get automated for you (e.g. alarm and attendee settings). And if you only use intents, your app doesn’t need the permissions you need for the content provider.

As of now you can do exactly four things:

  • You can open the Calendar app at a specific date
  • You can view events
  • You can create new events
  • You can edit events

Well, actually you can only do three things, since the last intent doesn’t work. More on this later.

From ICS onwards the Calendar is part of Android’s standard apps. So it is very unlikely that the Calendar app is missing. Nevertheless you should always test for the availability of Intents. I omit this in the code samples in the next paragraphs since these are examples only – but you should not! You can read more about this in my post about how to test for Intent availability.

Opening the Calendar app

Maybe you want to give the user the possibility to view her calendar. In this case you can use the ACTION_VIEW and CalendarContract.CONTENT_URI as the Uri to start the app.

You have to add the time at which you want to open the calendar. You can either do this by concatenating Strings or by using Android’s Uri.Builder helper class.

In the following code fragment I show how you would open the calendar with a date two month in the future:

Calendar cal = new GregorianCalendar(); 
cal.setTime(new Date()); 
cal.add(Calendar.MONTH, 2); 
long time = cal.getTime().getTime(); 
Uri.Builder builder = 
      CalendarContract.CONTENT_URI.buildUpon(); 
builder.appendPath("time"); 
builder.appendPath(Long.toString(time)); 
Intent intent = 
      new Intent(Intent.ACTION_VIEW, builder.build()); 
startActivity(intent); 

Creating an event

Probably more interesting is creating an event. In this case the action to use is ACTION_INSERT and the URI to use is Events.CONTENT_URI. What makes this option so compelling is that you do not have to add any Intent extras. You can open the event editor without any data – in which case only some default values of the form are prefilled as you can see in the next screen.

Form for entering events

Form for entering events

If the user has no calendar account added, Android shows a dialog that warns the user that no events can be added as long as no account exists. This is pretty common on the emulator – but should be the exception on a real device. Normally device vendors have a calendar with some sync adapter of their own. But even if this is not the case, your app will not crash. The next screenshot shows the message in this case.

Warning when no calendar account exists

Warning when no calendar account exists

The simplest code to create an event with an intent is this:

Intent intent = 
      new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
startActivity(intent); 

But if you want, you can add data so that the form is prefilled with these values. You can basically set all the data, that you can use to create events with the content provider. For attendees and alarms you have to use other constants, since they are not part of the Events class. Strangely Google has decided that for the start- end end-time of the event you also need special constants. Why they didn’t use the constants of the Events class is beyond me. This makes the code kind of ugly and the API harder to understand than necessary. As you can see in the next code fragment these constants from differing classes do not look that good:

Calendar cal = new GregorianCalendar(); 
cal.setTime(new Date()); 
cal.add(Calendar.MONTH, 2); 
Intent intent = new Intent(Intent.ACTION_INSERT); 
intent.setData(Events.CONTENT_URI); 
intent.putExtra(Events.TITLE, "Some Test Event"); 
intent.putExtra(Events.ALL_DAY, true); 
intent.putExtra(
      CalendarContract.EXTRA_EVENT_BEGIN_TIME, 
      cal.getTime().getTime()); 
intent.putExtra(
      CalendarContract.EXTRA_EVENT_END_TIME, 
      cal.getTime().getTime() + 600000); 
intent.putExtra(
      Intent.EXTRA_EMAIL, 
      "attendee1@yourtest.com, attendee2@yourtest.com"); 
startActivity(intent); 

Viewing an event

In addition to creating a new event you sometimes want users to view an event. Once again an intent is useful here because the presentation of the intent is done in a way that the user is accustomed to. But to do so, you need to have the event id – for which you need the content provider.

For the next example I assume that you already have the id for the event. In this case the code is really simple:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri.Builder uri = Events.CONTENT_URI.buildUpon();
uri.appendPath(Long.toString(yourEventId));
intent.setData(uri.build());
startActivity(intent);

That’s all nice and swell. Alas, the default Calendar app manipulates the back stack and pressing back does not jump back to your app but to the calendar view. That’s the correct behavior when started from the calendar widget but not when the calendar app has been called from another app.

Your users have to press back twice to get back to the point where they came from. And they will blame you for this even though it’s not your fault. Because of this try to avoid the need for viewing events. It might be better to open the calendar at the correct date.

I have filed a bug report for this issue. If you agree, that this is annoying, please star this issue.

And it’s not just me, at least one developer at StackOverflow complains about the same bug.

Editing an Event

The final Intent that the calendar app supports is editing an event. Well at least according to the Android documentation.

Now it would have been nice if it worked. But not so. What you actually see if you use the intent for editing is the read-only version of the editing activity. In this case you can only change minor stuff like the reminders or the timezone. Theoretically you can provide additional data – though this unsurprisingly also doesn’t work.

Add to this that the back button causes trouble again. When you click “Done” the Calendar-View is shown. The more natural behaviour would have been to save the changes and then return to where you came from. At least clicking “Cancel” or the back button works as expected.

This is pretty annoying since this is a very useful intent – or would be if it worked. If your app needs to edit events there is no other way to do so than to create the necessary form yourself. Not what users have come to expect in Android. And not what we developers love on Android.

I have also filed a bug report for this issue. Please vote for this as well.

For this bug I have also found another fellow StackOverflow user complaining about it.

Choosing between Intents and the CalendarContract provider

When to use which approach depends on the needs of your app. The following bullet points list some pros and cons of each approach:

Advantages of using intents

  • You do not need to use permissions
  • The user of your app can decide which backend calendar to use for an event
  • familiar interface of the calendar app
  • common behavior in Android

Disadvantages of intents

  • Only very few use cases are supported; an important one doesn’t work correctly
  • The consistency of the user experience within your app might get lost when opening the Calendar app.

Advantages of the content provider

  • Significant changes of nearly all data possible
  • The only way for sync adapters to sync calendar related data
  • Might happen in the background without the user knowing much about it

Disadvantages of the content provider

  • You have to add permissions to your app
  • If your app is not acting as a sync adapter you might not know which calendar id to use

Lessons learned

You have ssen how to leverage intents to open up the Calendar view at a specific date, how to create new events and how to view existing ones.

You have also learned about the weak spots of the app’s intents: The incorrect back behavior for viewing events and the total mess of the edit event intent.

Thus you have to choose carefully which and if intents are the correct way for your app to deal with events.

Half a Year of Blogging About Android Development

Exactly six months ago I published my “Hello World” post. And one week later my first post with serious content followed: Android: Checking Connectivity.

Over the last half year I have continuously blogged and there were only two weeks in which I didn’t publish any posts. According my general feeling my blog progresses nicely. And Google Analytics, G+ reshares and the number of G+ followers seem to confirm this. So, reason enough to celebrate :-)

I will share many stats with you, but if you do not care about numbers, please head directly to the sections about my plan to change the current hosting solution, my current unwillingness to offer a responsive version of this website and for what’s to expect in the coming months.

Published posts

Total number of posts published: 32 (my Hello World not included)

Tutorials published: 11

Quick tips published: 2

Obviously I should expand on the Quick tip type :-)

Usage stats

Visitors per day: Roughly 300 (on weekends less, on posting days about twice as much) – steadily increasing

Page views per day: Above 450

Bounce rate: 78 per cent (I do not know whether this is good or bad – if you blog, please let me know how you do in this regard)

Ratio of new vs. returning visitors: 61 to 39 (I also do not know what to make of this number)

Favorite topics

The two top posts are my tutorial on BroadcastReceivers and on making your app searchable. Both get about 50 hits each daily.

The topic with the most hits so far is the post about the library Crouton. This post caused the biggest traffic spike yet and was really loved on the three social media sites I use (Google plus, Reddit and DZone). But as was to be expected this post is nowhere near the previous two on daily views.

Generally speaking tutorials are liked much more. This also is no big surprise since they tend to get more search traffic.

Traffic sources

Search: 50%
Referrals: 30%
Direct traffic: 16%
Campaigns: 4%

Campaigns is an odd term. In my case this are visits originating from an RSS reader.

Referrals are all visits that come via a link from any other site. This can be social media sites, blog links, newsletters seen on the web or coming via a redirect and so on – unless it is a search result.

Search is obviously a visit via Google (Bing is nearly irrelevant with about half a per cent of all search traffic – yahoo is even worse).

Direct traffic are those people entering the domain directly into the browser. I can only assume that many people copy links before opening them, use Chrome’s incognito mode or hide the referrer in other ways. This number is definitely too high.

Referring blogs

A whopping ten per cent of all referrals (see above) come via Juhani Lehtimäkis blog androiduipatterns.com. That’s the next big traffic source directly after Reddit and Google plus. And these visitors are an especially interested crowd (low bounce rate, long duration of average visit).

So if anyone hasn’t been to his fantastic blog it’s about time to have a look. And since you’re in the right mood, why not buy his book “Smashing Android UI”? Should be in every Android developers and designers bag anyway! And, no, I do not get any affiliate commissions for this link!

Other blogs are also doing well. Readers coming from blogs are on average much more interested than those coming via social networking sites. I think this is not surprising. A reader of another blog found the content of that blog interesting. And if the other blogger recommends yet another blog, chances are good that the reader likes this blog as well.

So if you haven’t done so, please have a look at my blogroll. These blogs are highly recommended by me and all deal with Android development as well.

A big thank you to all those bloggers that have linked to my blog!

Newsletters

Apart from blogs another important source of readers of my blog are the newsletters Android Weekly, #AndroidDev Weekly and the newsletter of the French site FrAndroid.

Bounce rates with newsletter visitors is higher than those of blog referrals but those readers do visit more pages on average than those coming via social media or search.

Also thanks to the newsletter editors for linking to my blog.

Search

As mentioned, for my blog Google is the only search engine that counts. It’s responsible for 50 per cent of all visits. Since people search for a specific topic, the bounce rate is quite high.

The top five queries where people see my site on a results page all have to do with BroadcastReceivers. Unsurprisingly my tutorial about BroadcastReceivers is where most readers end, when coming from Google.

Google Analytics uses two stats for search. The first is the report about the top 1000 daily queries. The second report is about all searches where my blog showed up in the results.

For the 1000 top queries (do not ask me about this report, I still do not get it) my click-through-rate is 5 per cent, for all Search Impressions in total my click-through-rate is 7.5 per cent. From what I have read these are quite decent numbers. But if some fellow bloggers could shed some light on these two reports, I would be thankful.

Technology used by visitors

Since this is a developers blog, you probably are interested in the technology people use. So let me share some stats.

Mobile usage

Nearly 10 per cent of all visitors use mobile devices. Of all devices the Google Nexus is the top device. It accounts for more than three times the number of visitors than the next device – which is the iPad. The Nexus 7 is the third most used device and the fourth is one of the iPhones. So, there you have it. We Android users and devs are an open-minded crowd.

Still, Android usage is eight times that of iOS usage. No surprises here. But since Android offers a better variety of products, individual devices carry less weight.

The most interested readers are those using a Nexus 7 or a Galaxy Tab 10.1. They stay longer, come back more often and visit more pages. Other than for the Nexus 7 and Galaxy Tab 10.1 the bounce rate is quite high for mobile users.

OS share

Windows: 60%
Mac: 17%
Linux: 13%
Android: 8%
iOS: 1%

All others (Windows Phone, Symbian, Chrome OS, unidentifiable) account together for only 1 per cent.

Browser share

Chrome: 63%
Firefox: 21%
Safari: 4%
IE: 4%
Android Browser: 4%
Opera: 3%

I especially like the numbers for the Internet Explorer. I have suffered under this browser way too long!

Top Countries

United States: 15% (California alone 4%)
India: 11% (the city of Bangalore alone 3%)
Germany: 8%
France: 5%
Great Britain: 5%

Even though more French people read my blog than Brits, London is way ahead of Paris. But still, for a blog written in English, this is a surprising result. I guess it has to do with the FrAndroid newsletter mentioning this blog regularly.

Germany’s numbers probably are higher than Germany’s actual developer share simply because I am German myself and have many German G+ followers.

Social media

Now apart from search most people come to my blog via social media. In per cent of all visitors:

Reddit: 8%
Google plus: 6%
DZone: 3%
StackOverflow: 1.4%
Twitter: 0.5%

This is for the last month. The months before Reddit has had a much higher share of about three times that of Google plus. But my experience with Reddit has been quite mixed. Some posts go wild while others are duds or, worse, get downvoted rather quickly (which causes them to vanish from the Reddit site). I simply do not get Reddit.

The numbers for Twitter and Facebook are that low simply because I am no user of these sites. But I plan to use Twitter in the future. Why is that? Well, many interesting developers still do not use Google plus. Mark Murphy is probably the best-known of them, but not the only one. And of course, Twitter users love to follow and reshare links. So this should open my blog to new readers.

I really like DZone. I have found some nice blogs via their site. But it is not the biggest traffic engine. Anyway: If anyone at DZone reads this: Please offer an API. For a social media site having no API is simply unbelievable. Apps that monitor social media coverage cannot deliver anything about DZone at the moment. That’s sad! And of course I would like to see an Android app for DZone. Yours truely would love to help create one ;-)

Why I have to move my blog

Right now I am using shared hosting. This was very easy to set up, but in the end it is nevertheless a pain. The shared hosting I use is way too slow to meet my expectations. Performance is simply not sufficient. Just imagine I had an even bigger reader base. Some of you probably would walk away – not willing to wait any longer for responses of my server.

Furthermore the package I am currently using, doesn’t offer the chance to use gzip compression. Page Speed Score is still 86 (of 100), which is okay. But that’s not how it feels.

All in all I think I have to switch to something better. Probably Dedicated hosting. Maybe a vhost server. I am evaluating options at the moment. But I will change the provider (or the package). So expect to see a significant improvement in performance pretty soon.

No mobile version? No responsive design? Is this gonna change?

To be honest: Mobiles are getting bigger at a fast rate and screen real estate has improved a lot. Thus I have no plans to do a lot in this regard. So while I am a big proponent of responsive design for Android apps, I do not consider it necessary for this blog. Of course, if a lot of you would post in the comments that you miss this, I would reconsider. It’s up to you!

What I will change though, is how a printout looks. I often print blog posts of others if I like the content and expect to refer to the post more than once. Or for posts that look important but are pretty longish. But my blog simply doesn’t look good when printed. Which is not okay and which I plan to correct. You shouldn’t have to wait too long.

What’s to expect in coming months

I already started my series about libraries with my post about Crouton. I intend to make this a regular post style, appearing once a month. The next one will be about EventBus.

Furthermore book reviews are in the pipeline. Probably one review per month. It depends on what books get published and how much time I have to read them. Actually a book review will be on of my next posts. Disclaimer: I will add Amazon affiliate links. Just ignore them if you don’t like this kind of stuff. But if you want to support my caffeine-level, follow these links if you intend to buy the books anyway :-)

I also plan on doing some interviews with fellow developers, may be even some Googlers and – if possible – Android-savvy designers as well. This is not gonna happen this year but hopefully at the beginning of the next year.

I might also occasionally have a look at other blogs. Maybe coupled together with an interview of the blogger. I like this idea, but I am not sure if this adds value. If you would like to see this let me know.

Apart from this, I simply will continue what I did the last months. Complete with occasional bug reports, rants, tutorials, in-depth posts and short quick tips.

Thanks to all of you for your support so far!

Subscribe to RSS Feed My G+-Profile Follow me on Twitter!