18 September 2013

Roy Clarkson (@royclarkson) and I gave a talk at SpringOne2GX 2013 in which we talked about building REST services with an eye towards consuming those services on mobile platforms like Android and iOS. This talk demonstrates the progressive evolution of an application using Spring MVC, Spring HATEOAS, Spring Data REST, Spring Security, Spring Security OAuth, and Spring Android. The code's benefited from a lot of help from Rob Winch.

I am pulling this blog together to introduce how we used the ActionBar Sherlock project in the sample application. There is nothing here related to Spring, but I thought the whole process was hard enough that some notes might help someone else.

What is an ActionBar?

From the documentation, the ActionBar:

  1. Provides a dedicated space for giving your app an identity and indicating the user's location in the app.
  2. Makes important actions prominent and accessible in a predictable way (such as Search).
  3. Supports consistent navigation and view switching within apps (with tabs or drop-down lists).

The ActionBar, pictured above in an image from the Google documentation, provides a sort of hub for interaction UIs like menus, toolbars, etc., in your application. It's also a nice place to install a widget like a search field that can provide functionality and trigger behavior independent of any single view.

The ActionBar API (android.app.ActionBar), however, is only available in Android API level 11 and greater. There is a sort of backwards compatible API called the Android Support Library (android.support.v7.app.ActionBar) that works with versions lower than API level 11.

What is the ActionBar Sherlock?

From the ActionBar Sherlock website:

ActionBarSherlock is an extension of the support library designed to facilitate the use of the action bar design pattern across all versions of Android with a single API.

So, it provides a clean API that wraps and adapts to existing implementations if available, and otherwise does a remarkable job simulating the effect in older versions of the platform, all with no change to your code.

All of this works in a consistent way on the ActionBar. On devices that support the hardware Menu button, this menu is available using that button. Otherwise it shows up as shown here, as part of the ActionBar.

Our Sample Application

In our sample application, the user has the ability to:

Using ActionBar Sherlock

The sample application uses Android Fragments to make the layout more dynamic inside of a single Activity, so in practice there is only one Activity that needs to extend the SherlockFragmentActivity class.

To use the ActionBar, an Activity should extend one of the ActionBar Sherlock-provided Activity instances. This way, you get a reference to the ActionBar via the getActionBar() method. Conveniently, you won't really need that reference, though.

Below, I demonstrate how to setup a search field in the application. The Activity#onCreateOptionsMenu(Menu) callback method gives you a pointer to the menu reference which you may use to add menu items.

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        this.menu = menu;

        SearchManager searchManager = (SearchManager) 
               activity.getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = new SearchView(activity);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(activity.getComponentName()));
        searchView.setQueryHint(getString(R.string.search_hint));
        searchView.setIconified(true);
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                runQuery(query);
                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return true;
            }
        });

        // search menu item       
        MenuItem menuItem  = menu.add( getString(R.string.search));
        menuItem.setTitle(title);
        menuItem.setActionView(searchView);
        menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);        

         // ..

     }

Adding the ActionBar project to your Maven Build

I had to go through some fits to make the Android build work perfectly as the ActionBar Sherlock project is delivered as an Android .apk bundle, not a .jar. Check out the build file for the nitty gritty.