Selecting Items of a RecyclerView using StateListDrawables

Last week, after I published my introduction to RecyclerView Paul Betts asked on Twitter whether ItemDecorators are useful for displaying the selection state of items.

Well, I think using them for selection is not the right way to go. Instead, I think that you should stick with StateListDrawables and the activated state.

The use case of the sample

In this sample the user can select multiple items that are shown in purple. The first item gets selected using a long click. Any subsequent click will select or deselect items. Users can also deselect items, that were previously selected, with a single click. The user can then use a bulk delete operation on all selected items. The user should be able to see the number of currently selected items.

Obviously that sounds a lot like a contextual action bar (CAB), which is what I used. BTW: As you can see in the screenshot, the CAB doesn’t look like I expected it to look. It should use my android:colorPrimaryDark for the contextual app bar (Material lingo). But either the theming guide for material design is not correct, or maybe it’s the current L preview, or – more likely – it’s my code. Any takers? Please let me know, if you know what’s wrong here. Thanks!

Here’s a screenshot of the final result. You can also find a video near the end of this post.

RecyclerView with Contextual ActionBar and selected items

RecyclerView with Contextual ActionBar and selected items

Overview

The solution that I suggest is Adapter-based. As you might recall from my last post, RecyclerView doesn’t care about the visual representation of individual items. Thus I quickly ruled out to subclass RecyclerView.

RecyclerView doesn’t itself need to know about the set of items nor about the state these items are in. In this way my proposed solution differs from the way you did selections with ListView or GridView in the past. There you checked items directly using the setItemChecked() method and you set the kind of selection mode with setChoiceMode().

With RecyclerView any information about the data set belongs to your RecyclerView.Adapter subclass. Thus anything required to show the selection state of items should also be in your RecyclerView.Adapter subclass.

The adapter not only stores information about the state of each item, but it also creates the views for each items. That’s why I use the adapter for setting the activated state.

Methods for setting the selected state

Based on this use case, I chose to add the following methods to my RecyclerView.Adapter subclass:

  • void toggleSelection(int pos)
  • void clearSelections()
  • int getSelectedItemCount()
  • List<Integer> getSelectedItems()

With toggleSelection() an item changes its selection state. If it was previously selected it gets deselected, and vice versa.

You can always clear all selections with clearSelections(). You shouldn’t forget to do that when you finish the action mode.

The other methods get the number of currently selected items and all positions of the currently selected items.

Necessary changes to the adapter

Here’s the relevant part of my Adapter:

public class RecyclerViewDemoAdapter
        extends RecyclerView.Adapter
                <RecyclerViewDemoAdapter.ListItemViewHolder> {

   // ...
   private SparseBooleanArray selectedItems;
   
   // ...

   public void toggleSelection(int pos) {
      if (selectedItems.get(pos, false)) {
         selectedItems.delete(pos);
      }
      else {
         selectedItems.put(pos, true);
      }
      notifyItemChanged(pos);
   }
   
   public void clearSelections() {
      selectedItems.clear();
      notifyDataSetChanged();
   }
   
   public int getSelectedItemCount() {
      return selectedItems.size();
   }
   
   public List<Integer> getSelectedItems() {
      List<Integer> items = 
            new ArrayList<Integer>(selectedItems.size());
      for (int i = 0; i < selectedItems.size(); i++) {
         items.add(selectedItems.keyAt(i));
      }
      return items;
   }

   // ...

}

Notice how I used notifyDataSetChanged() and notifyItemChanged(). That’s necessary because I do not have access to the View object itself and thus cannot set the activated state directly. Instead I have to tell Android to ask the Adapter for a new ViewHolder binding.

How to use those methods from within the Activity

If you have used ListViews with the Contextual ActionBar in the past, you know that for selecting multiple items you had to set the choice mode to CHOICE_MODE_MULTIPLE_MODAL and implement the AbsListview.MultiChoiceModeListener interface to achieve the desired result. See this guide on Android’s developer site for more details. Now since RecyclerView doesn’t offer this interface (and rightly so), you have to find a way around this.

My solution is to use the GestureDetector to detect long presses. You can find this code at the end of the Activity. In the long-press callback, I create the actionmode, detect which view was pressed and call toggleSelection() on the adapter.

public void onLongPress(MotionEvent e) {
   View view = 
      recyclerView.findChildViewUnder(e.getX(), e.getY());
   if (actionMode != null) {
      return;
   }
   actionMode = 
      startActionMode(RecyclerViewDemoActivity.this);
   int idx = recyclerView.getChildPosition(view);
   myToggleSelection(idx);
   super.onLongPress(e);
}

private void myToggleSelection(int idx) {
   adapter.toggleSelection(idx);
   String title = getString(
         R.string.selected_count, 
         adapter.getSelectedItemCount());
   actionMode.setTitle(title);
}

For the actionmode to work, the activity has to implement the ActionMode.Callback interface. I won’t go into this. It’s described in detail in the official menu guide on the Android site.

To understand of how selections work only two of this interface’s methods are interesting:

  • onActionItemClicked()

    Android calls this method when the user presses the delete icon. In this method I get the list of selected items from the adapter and call the removeData() method of the adapter for each item – so that Android can smoothly animate them – as shown in the previous post. And, of course, I have to finish the action mode afterwards.

  • onDestroyActionMode()

    Android calls this method when it’s leaving actionmode prior to showing the normal ActionBar (app bar) again. This happens either when the user selects the check mark or when he/she selects the delete icon.

Here’s the code for these two methods:

@Override
public boolean onActionItemClicked(
         ActionMode actionMode, 
         MenuItem menuItem) {
   switch (menuItem.getItemId()) {
      case R.id.menu_delete:
         List<Integer> selectedItemPositions = 
               adapter.getSelectedItems();
         for (int i = selectedItemPositions.size() - 1; 
               i >= 0; 
               i--) {
            adapter.removeData(selectedItemPositions.get(i));
         }
         actionMode.finish();
         return true;
      default:
         return false;
   }
}

@Override
public void onDestroyActionMode(ActionMode actionMode) {
   this.actionMode = null;
   adapter.clearSelections();
}

The StateListDrawable XML file

So far I have shown you how to select items and set the activated state. To finally highlight those items I use StateListDrawables.

A StateListDrawable is a drawable that changes its content based on the state of the view. You can define those in XML files. The first matching entry for a given state determines which drawable Android uses. Since I only care about the activated state the XML file is actually very simple:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android=
      "http://schemas.android.com/apk/res/android">
   <item android:state_activated="true" 
         android:drawable="@color/primary_dark" />
   <item android:drawable="@android:color/transparent" />
</selector>

And of course you have to use this StateListDrawable somewhere. I use it as the background for each item:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container_list_item"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/statelist_item_background">
    <include layout="@layout/common_item_layout" />
</RelativeLayout>

The following video shows the result of this post’s changes:

A short video showing the Contextual ActionBar and the selection of items

Sample project

You can download the sample from my github page. I have tagged the revision of last week’s post with “simpleSample” while the revision for this week uses the tag “selectionSample”.

Feel free to submit pull requests if you have suggestions on how to improve the code.

And that’s it for today

This was a short example of how to make use of the RecyclerView.Adapter and how to benefit from those abstractions. I guess I won’t go into much more detail about the adapter in future posts. But I recommend that you take a look at Gabriele Mariotti’s great example of how to use an RecyclerView.Adapter with sectioned lists.

I hope this post helps you in your work with RecyclerView.Adapters. Selection is just one of the many things an adapter is useful for. If you have a look at Gabriele’s gist, you can see how to use your adapter to support different view types. Just keep in mind the separation of concerns and don’t mix responsibilities.

A First Glance at Android’s RecyclerView

At this year’s Google I/O, Google released a preview to the upcoming Android version. The so called L Developer Preview. This is a very big improvement over previous releases and I really love that Google is doing this. I think we all benefit by this decision. As developers and as consumers alike!

Part of this preview are two new views: RecyclerView and CardView. This post gives you an introduction to the RecyclerView, it’s many internal classes and interfaces, how they interact and how you can use them.

Let me start with the good news: RecyclerView is part of the support library. So you can use it right now. Ok: You can use it as soon as the final support lib accompanying the L release gets released. So better to familiarize yourself with it right away :-)

Sample project

The screenshots and the video at the end of the post show the sample project for this post in action. You can find the source of this sample at github. Keep in mind that the RecyclerView API is not yet finalized. Google might still change things that could break the sample when they release the final version of Android L.

What’s with this odd name? Why RecyclerView?

This is how Google describes RecyclerView in the API documentation of the L preview release:

A flexible view for providing a limited window into a large data set.

So RecyclerView is the appropriate view to use when you have multiple items of the same type and it’s very likely that your user’s device cannot present all of those items at once. Possible examples are contacts, customers, audio files and so on. The user has to scroll up and down to see more items and that’s when the recycling and reuse comes into play. As soon as a user scrolls a currently visible item out of view, this item’s view can be recycled and reused whenever a new item comes into view.

The following screenshots of the sample app illustrate this. On the left is the sample app after the initial start. When you scroll the view up, some views become eligible for recycling. The red area on the right screenshot, for example, highlights two invisible views. The recycler can now put these views into a list of candidates to be reused should a new view be necessary.

These two screens show what recycling means. On the right two views are eligible for reuse

These two screens show what recycling means. On the right two views are eligible for reuse

Recycling of views is a very useful approach. It saves CPU resources in that you do not have to inflate new views all the time and it saves memory in that it doesn’t keep plenty of invisible views around.

Now, you might say: That’s nothing new. And you’re right! We had that with ListView for a very long time. The concept of recycling views itself it not new. But while you previously had a ListView where the appearance, recycling and everything was tightly coupled, Google now follows a much better, a much more flexible approach with the new RecyclerView. I really like the approach Google has taken here!

RecyclerView doesn’t care about visuals

Here’s the thing: While with Listview we had tight coupling, Google now uses an approach where the RecyclerView itself doesn’t care about visuals at all. It doesn’t care about placing the elements at the right place, it doesn’t care about separating any items and not about the look of each individual item either. To exaggerate a bit: All RecyclerView does, is recycle stuff. Hence the name.

Anything that has to do with layout, drawing and so on, that is anything that has to do with how your data set is presented, is delegated to pluggable classes. That makes the new RecyclerView API extremely flexible. You want another layout? Plug in another LayoutManager. You want different animations? Plug in an ItemAnimator. And so on.

Here’s the list of the most important classes that RecyclerView makes use of to present the data. All these classes are inner classes of the RecyclerView:

The most important classes of the RecyclerView API
Class Usage
Adapter Wraps the data set and creates views for individual items
ViewHolder Holds all sub views that depend on the current item’s data
LayoutManager Places items within the available area
ItemDecoration Draws decorations around or on top of each item’s view
ItemAnimator Animates items when they are added, removed or reordered

In the next paragraphs I will briefly describe what each class or interface is about and how RecyclerView uses it. In future posts I will revisit some of these classes, write about them in detail and show you how to customize them for your project’s needs.

ViewHolder

ViewHolders are basically caches of your View objects. The Android team has been recommending using the ViewHolder pattern for a very long time, but they never actually enforced the use of it. Now with the new Adapter you finally have to use this pattern.

It’s a bit weird that Google waited so long to enforce the usage of the ViewHolder pattern, but better late than never. If you do not know about the ViewHolder pattern, have a look at this Android training session. It uses the old Adapter, but the pattern itself hasn’t changed.

Also searching for ViewHolder should yield plenty of hits to further blog posts. For example this post by Antoine Merle about ListView optimizations.

One thing that is specific to any RecyclerView.ViewHolder subclass is that you can always access the root view of your ViewHolder by accessing the public member itemView. So there’s no need to store that within your ViewHolder subclass.

And should you decide to override toString() have a look at the base class. Its toString() implementation prints some useful information you should consider to use for your log messages as well.

Here’s the code for the ViewHolder of the sample project. The ViewHolder is an inner class of the sample project’s Adapter:

public final static class ListItemViewHolder extends RecyclerView.ViewHolder {
   TextView label;
   TextView dateTime;
   
   public ListItemViewHolder(View itemView) {
      super(itemView);
      label = (TextView) itemView.findViewById(R.id.txt_label_item);
      dateTime = (TextView) itemView.findViewById(R.id.txt_date_time);
   }
}

RecyclerView.Adapter

Adapters fulfill two roles: They provide access to the underlying data set and they are responsible for creating the correct layout for individual items. Adapters always were part of Android and were used in many places. ListView, AutoCompleteTextView, Spinner and more all made use of adapters. All those classes inherit from AdapterView. But not so RecyclerView.

For the new RecyclerView Google has decided to replace the old Adapter interface with a new RecyclerView.Adapter base class. So say good bye to things like SimpleCursorAdapter, ArrayAdapter and the like. At least in their current incarnation.

Currently there is no default implementation of RecyclerView.Adapter available. Google might add some later on, but I wouldn’t bet on this. For Animations to work properly, cursors and arrays aren’t the best fit, so porting the current Adapter implementations might not make too much sense.

Since RecyclerView.Adapter is abstract you will have to implement these three methods:

  • public VH onCreateViewHolder(ViewGroup parent, int viewType)
  • public void onBindViewHolder(VH holder, int position)
  • public int getItemCount()

The VH in the method signatures above is the generic type parameter. You specify the concrete type to use when you subclass the RecyclerView.Adapter. You can see this in line 3 of the next code sample.

The most basic adapter for the sample layout looks like this:

public class RecyclerViewDemoAdapter extends 
        RecyclerView.Adapter
        <RecyclerViewDemoAdapter.ListItemViewHolder> {

    private List<DemoModel> items;

    RecyclerViewDemoAdapter(List<DemoModel> modelData) {
        if (modelData == null) {
            throw new IllegalArgumentException(
                  "modelData must not be null");
        }
        this.items = modelData;
    }

    @Override
    public ListItemViewHolder onCreateViewHolder(
            ViewGroup viewGroup, int viewType) {
        View itemView = LayoutInflater.
                from(viewGroup.getContext()).
                inflate(R.layout.item_demo_01, 
                        viewGroup,
                        false);
        return new ListItemViewHolder(itemView, viewType);
    }

    @Override
    public void onBindViewHolder(
            ListItemViewHolder viewHolder, int position) {
        DemoModel model = items.get(position);
        viewHolder.label.setText(model.label);
        String dateStr = DateUtils.formatDateTime(
                viewHolder.label.getContext(),
                model.dateTime.getTime(),
                DateUtils.FORMAT_ABBREV_ALL);
        viewHolder.dateTime.setText(dateStr);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    public final static class ListItemViewHolder 
           extends RecyclerView.ViewHolder {
        // ... shown above in the ViewHolder section
    }
}

RecyclerView.LayoutManager

The LayoutManager is probably the most interesting part of the RecyclerView. This class is responsible for the layout of all child views. There is one default implementation available: LinearLayoutManager which you can use for vertical as well as horizontal lists.

You have to set a LayoutManager for your RecyclerView otherwise you will see an exception at Runtime:

08-01 05:00:00.000  2453  2453 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView$LayoutManager.onMeasure(android.support.v7.widget.RecyclerView$Recycler, android.support.v7.widget.RecyclerView$State, int, int)' on a null object reference
08-01 05:00:00.000  2453  2453 E AndroidRuntime: 	at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:1310)

Only one method of LayoutManager is currently abstract:

  • public LayoutParams generateDefaultLayoutParams()

But there is another one where the code states that you should overrride it since it’s soon going to be abstract:

public void scrollToPosition(int position) {
   if (DEBUG) {
      Log.e(TAG, "You MUST implement scrollToPosition. It will soon become abstract");
   }
}

That’s very weird! Why not make it abstract right away? Anyway: Better you override this one to be on the safe side for when Google releases the final version of L.

But only overriding those two methods won’t get you very far. After all the LayoutManager is responsible for positioning the items you want to display. Thus you have to override onLayoutChildren() as well.

This method also contains a log statement stating “You must override onLayoutChildren(Recycler recycler, State state)”. Ok, then make it abstract :-) Luckily there’s still plenty (?) of time to change that into a proper abstract method for the final release of L. We all make mistakes. After all, my “Stupid stuff devs make” series is all about blunders that I made. So don’t get me wrong. No hard feelings here!

LinearlayoutManager

The LinearLayoutManager is currently the only default implementation of LayoutManager. You can use this class to create either vertical or horizontal lists.

The implementation of LinearLayoutManager is rather complex and I only had a look at some key aspects. I will return to this implementation in my post about custom LayoutManagers.

To use the LinearLayoutManager you simply have to instantiate it, tell it which orientation to use and you are done:

LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(currPos);
recyclerView.setLayoutManager(layoutManager);

LinearLayoutManager also offers some methods to find out about the first and last items currently on screen:

  • findFirstVisibleItemPosition()
  • findFirstCompletelyVisibleItemPosition()
  • findLastVisibleItemPosition()
  • findLastCompletelyVisibleItemPosition()

Surprisingly these methods are not part of the source code in the SDK folder, but you can use them as they are part of the binaries. As I cannot imagine those being removed, I’m sure you’ll find these in the final L release as well.

Other methods help you get the orientation of the layout or the current scroll state. Others will compute the scroll offset. And finally you can reverse the ordering of the items.

Since I’m going to write an extra post about LayoutManagers this should suffice for now.

RecyclerView.ItemDecoration

With an ItemDecoration you can add an offset to each item and modify the item so that items are separated from each other, highlighted or, well, decorated.

You do not have to use an ItemDecoration. If, for example, you use a CardView for each item, there’s no need for an ItemDecoration.

On the other hand you can add as many ItemDecorations as you like. The RecyclerView simply iterates over all ItemDecorations and calls the respective drawing methods for each of them in the order of the decoration chain.

The abstract base class contains these three methods:

  • public void onDraw(Canvas c, RecyclerView parent)
  • public void onDrawOver(Canvas c, RecyclerView parent)
  • public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent)

Anything you paint in onDraw() might be hidden by the content of the item views but anything that you paint in onDrawOver() is drawn on top of the items. If you simply create a bigger offset and, for example, use this offset to paint dividers, this of course is of no importance. But if you really want to add decorations, you have to use onDrawOver().

The LayoutManager calls the getItemOffset() method during the measurement phase to calculate the correct size of each item’s views. The outRect parameter might look a bit odd at first. Why not use a return value instead? But it really makes a lot of sense, since this allows RecyclerView to reuse one Rect object for all children and thus save resources. Not necessarily nice — but efficient.

One thing I didn’t expect considering the name of the class is that the onDraw()/onDrawOver() methods are not called for each item, but just once for every draw operation of the RecyclerView. You have to iterate over all child views of the RecyclerView yourself.

I will explain this in more detail in a follow-up post about writing your own ItemDecorations.

RecyclerView.ItemAnimator

The ItemAnimator class helps the RecyclerView with animating individual items. ItemAnimators deal with three events:

  • An item gets added to the data set
  • An item gets removed from the data set
  • An item moves as a result of one or more of the previous two operations

Luckily there exists a default implementation aptly named DefaultItemAnimator. If you do not set a custom ItemAnimator, RecyclerView uses an instance of DefaultItemAnimator.

Obviously for animations to work, Android needs to know about changes to the dataset. For this Android needs the support of your adapter. In earlier versions of Android you would call notifyDataSetChanged() whenever changes occured, this is no longer appropriate. This method triggers a complete redraw of all (visible) children at once without any animation. To see animations you have to use more specific methods.

The RecyclerView.Adapter class contains plenty of notifyXyz() methods. The two most specific are:

  • public final void notifyItemInserted(int position)
  • public final void notifyItemRemoved(int position)

The following video shows the result of an addition as well as a removal of an item in the sample app:

A short video showing the default animations for the removal and addition of elements

Listeners

RecyclerView also offers some rather generic listeners. Once again you can safely forget everything you used to use up to now. There is no OnItemClickListener or OnItemLongClickListener. But you can use an RecyclerView.OnItemTouchListener in combination with gesture detection to identify those events. A bit more work and more code to achieve the same result. I still hope for Google to add those Listeners in the final release. But whether those Listeners will be added is as an open question.

Combining all classes

You combine the classes either in a fragment or an activity. For the sake of simplicity my sample app uses activities only.

First of all here’s the layout file containing the RecyclerView:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".RecyclerViewDemoActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        tools:listitem="@layout/item_demo_01"
        />

    <ImageButton
        android:id="@+id/fab_add"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_width="@dimen/fab_size"
        android:layout_height="@dimen/fab_size"
        android:layout_gravity="bottom|right"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="16dp"
        android:background="@drawable/ripple"
        android:stateListAnimator="@anim/anim"
        android:src="@drawable/ic_action_add"
        android:elevation="1dp"
        />
</RelativeLayout>

As you can see, nothing special here. You do not define the orientation or stuff like that on the RecyclerView. Actually RecyclerView itself makes no use of the attributes, it passes them on to the parent (which is ViewGroup) and that’s it.

There is one place within RecyclerView where an AttributeSet is used and that is in the generateLayoutParams() method:

@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
   if (mLayout == null) {
      throw new IllegalStateException("RecyclerView has no LayoutManager");
   }
   return mLayout.generateLayoutParams(getContext(), attrs);
}

In this snippet the RecyclerView passes the AttributeSet on to the LayoutManager.

The Java code is also pretty simple:

setContentView(R.layout.activity_recyclerview_demo);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
recyclerView.setLayoutManager(layoutManager);

// allows for optimizations if all item views are of the same size:
recyclerView.setHasFixedSize(true);

// For the sake of simplicity I misused the Application subclass as a DAO
List<DemoModel> items = RecyclerViewDemoApp.getDemoData();
adapter = new RecyclerViewDemoAdapter(items);
recyclerView.setAdapter(adapter);

RecyclerView.ItemDecoration itemDecoration =
        new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
recyclerView.addItemDecoration(itemDecoration);

// this is the default; 
// this call is actually only necessary with custom ItemAnimators
recyclerView.setItemAnimator(new DefaultItemAnimator());

// onClickDetection is done in this Activity's OnItemTouchListener
// with the help of a GestureDetector;
// Tip by Ian Lake on G+ in a comment to this post:
// https://plus.google.com/+LucasRocha/posts/37U8GWtYxDE
recyclerView.addOnItemTouchListener(this);
gesturedetector =
        new GestureDetectorCompat(this, new RecyclerViewDemoOnGestureListener());

Connecting all those elements together roughly consists of these steps:

  1. Get a reference to your RecyclerView
  2. Create a LayoutManager and add it
  3. Create an Adapter and add it
  4. Create zero or more ItemDecorations as needed and add them
  5. Create an ItemAnimator if needed and add it
  6. Create zero or more listeners as needed and add them

All in all about 30 lines of code.

Now of course this is misleading. That’s only the glue code. The really interesting stuff is in RecyclerView's many inner classes which you can subclass and tweak to your needs. That’s where the real work is done.

But the separation of concerns Google created helps you stick to one task within one implementation and it should make reuse easier to achieve. That’s why I like RecyclerView and its ecosystem. I’m not afraid to criticize big G, but that’s well done, Google!

Gradle integration

To use RecyclerView you have to add it to your gradle file. Adding the support library alone is not enough:

dependencies {
   //...
   compile 'com.android.support:recyclerview-v7:+'
   //...
}

Is that the final API?

Of course I do not know if the concrete implementations that the preview contains will be in the final release of Android L. But I guess so. And I expect some additions as well as minor changes to the API, based on bug reports and developer feedback.

Google itself gives one hint in the current API documentation about more stuff to come. The documentation for the RecyclerView.LayoutManager class contains this nugget:

Several stock layout managers are provided for general use.

So we can expect more LayoutManagers. Which, of course, is good. Furthermore I expect at least one default ItemDecoration as well. After all the support library’s sample project contains a DividerItemDecoration, which works well with the LinearLayoutManager.

I’m more skeptical about adapters. While an ArrayAdapter (or better yet, ListAdapter) is very well possible, I am more doubtful about a CursorAdapter since cursors do not lend themself easily to the new addition and removal notifications within the Adapter.

Lucas Rocha’s TwoWayView to simplify your life

I strongly recommend to have a look at Lucas Rocha’s TwoWayView project. He has updated his project to work with RecyclerView and has done a great deal to make using RecyclerView a lot easier. For many use cases the default layouts he provides should suffice. And he also provides support for custom LayoutManagers. Which are simpler to write using his framework than with the base RecyclerView.

Take a look at his project and check out if it covers all you need. Using it helps you get rid of some of RecyclerView‘s complexity.

For more information about his project see his blog post about how TwoWayView extends and simplifies RecyclerView.

To learn about news about this project follow Lucas Rocha on Google plus or Twitter.

I will cover TwoWayView in this series as well – so stay tuned :-)

Report bugs!

We currently have a developer preview. The first time Google does this for Android. Really nice. But of course this preview is not free of bugs. To help us all get a more stable final release, give feedback or issue bug reports, if you encounter anything that bothers you or is a bug. There is a special L preview issue tracker.

And that’s it for today

I started this post as part of the preparation for my talk at the July meetup of the Dutch Android User Group.

I had much fun presenting about this topic at the July meetup of the Dutch Android User Group. And I had fun digging into this topic – and still have. Reading the source of RecyclerView and its many inner classes is really interesting. Thanks to the organizers for giving me the opportunity to speak about this topic and for forcing me to dig into this stuff :-)

At Utrecht I had 15-20 minutes for my talk. How I managed to get it done in time is still a mystery to me. As you can see there’s a lot to talk about – and this post is only the beginning.

Until next time!

About Cyril Mottier’s “Shaping the Future of Android With Dart” – Some Additional Thoughts

This post is inspired by Cyril Mottier’s post about Dart for Android. If you haven’t read it already, please read it first.

Mostly I think Cyril’s arguments are valid.

I wouldn’t object to another language besides Java. Especially since the ability to use the new features of Java 8 might still be far away on Android.

But what about Scala, Groovy or the like, you might ask. Well, I think Dart being a first class, Google supported citizen would be another matter altogether. Despite the fact that I agree mostly with Cyril’s post, I think the post needs some kind of reply. And as much as I love Google plus, I think it’s not the appropriate forum for my reply. So I stick to my old-fashioned blog – with it’s even more old-fashioned look :-)

I do not know whether Dart is a superb language. I only have had quick perfunctory glances on slides or the odd look at the dartlang.org website whenever the topic Dart crept up. I also missed the Google Dart flight school this winter and haven’t develop anything decent in Dart at all. Yet from what I’ve read it looks like a decent enough and modern language that I would like to dig into. So Google bringing it to Android? That would be a very good reason for me to finally have a deeper look :-)

What’s important: Whatever Google comes up with, I strongly believe it’s going to run on ART. I wouldn’t be too surprised to learn that the initial reason to create a new VM in the first place, was inspired by Google’s wish to support other languages better. But as everything in this post, that’s just mere speculation. Pure guesswork.

There is a big reason for this: It’s the easiest path to migration. It allows people to keep using existing libraries (no matter whether those are plain old Java libraries or specific Android library projects). If those libraries couldn’t be used anymore, any other language would have a very difficult start.

It might also allow different teams of bigger organizations (think Facebook, Twitter, or those over-careful and very slow-movers like banks and insurances) to use both languages for one app (or app family). The hip front end team already uses Dart while those taking care of the database, synchronization and what not, keep using Java (for the time being). Cyril left this one very vague. I can’t understand why? For me that’s a necessity. Without it there’s no successful path to a quick adoption.

If there is one thing, where I didn’t agree with Cyril, it’s his paragraph, where he suggests that Dart could be

  • the one
  • language for all of Google’s projects. Such that Google could get rid of Python, Java, C++ and whatever else they use. I don’t think that’s feasible. For two reasons:

    1. The question of existing libraries exists for Google projects as well. Of course Google could reinvent the wheel all the time – they have enough people to do so. But that would be a foolish waste of energy. I don’t think it’s likely that Google is going to do that.
    2. One language is rarely suited for all kind of development efforts. That was never true for Java, has never been true for C and probably is not true for Dart as well. For one it’s a VM language again. So whenever Google used C or C++ instead of Java or anything else, they will continue to do so instead of using Dart. And there’s also the matter of the existing code base and libraries only in use within Google itself. Maybe my knowledge of Dart is too superficial to see how to do that efficiently with Dart. So that reason might not be valid at all. But my guess is, that it is.

    And don’t forget to star issue 19266 if you want to see Dart on Android.

    One last thing: Generally speaking: I hate speculations. So me taking part at a speculative rumour mill, is a big exception. Let me know if you like this kind of post. And of course, what you think about this topic. I’m interested in what you’ve got to say. Am I totally off? Does this sound reasonable? Is it worth speculating at all?

    Stupid mistakes devs make, part I: Taking app messages at face value

    This is a new series about programming blunders I make. Stuff that keeps me looking for solutions in all the wrong places while the answer most often is glaringly simple. If only I knew that right away!

    I am sorry for the generalization in the headline – of course it’s only me doing stupid stuff like that ;-)

    Mistake of the day

    Yesterday I was happily coding the sharing action for my upcoming app. This particular ShareActionProvider of the app lets users share a picture of their progress with keeping bad habits in check. I create an image and make it available to other apps via a content:// Uri. Nothing spectacular about that.

    You might know that the Email app asks your ContentProvider for the display name and the file size of the shared image. The image in question is about 20K in size. That’s far from being an overly big picture. Nevertheless I got the message that the attachment was too large:

    Toast showing that the attachment was too large

    Toast showing that the attachment was too large

    This left me wondering, what might possibly be wrong. I looked at the log messages. Check. I looked at the size of the stored image. Check. I debugged into my content provider to see that it reported the correct file size. Check. Starting to go out of ideas I even adb pulled the file and opened it in an image viewer. Check – it indeed was an image. I had another look at logcat. Check. All fine. So what the heck… My curse level had increased considerably! Never a good sign.

    But wait a moment. One of those checks above was not correct. Actually two of those were not correct. And – to be honest – just assuming that the message of the Email app was correct, probably was the first mistake. It totally misled me – and even worse: I let it do that.

    Finally I looked a bit more carefully. It turns out that I stopped debugging my content provider too early. And that I grepped logcat too rigorously.

    My content provider crashed shortly after the line where I stopped debugging, assuming everything to be perfectly fine. This assumption proved to be very wrong, since my code ran into a ClassCastException :-(

    And I didn’t see it in logcat because I renamed my package a few days ago, but didn’t rename my logging tag. The tag was the final part of the old app package name. And I grepped only for this tag – which proved to be very stupid! With this clever way of grepping any hints of stacktraces were gone.

    Finally: I didn’t notice this problem in any tests, because I do not work test first and simply had no tests for the sharing part of my provider.

    BTW: I do neither get the “File too large to attach” message on an old API level 8 device, nor on my GNex or my N5. Alas I had my Nexus 7 used for testing, which I update rarely since it’s a testing device only. The Email app seems to have been fixed. So with any of my other testing devices, I probably wouldn’t have had the same problems. It was just one of those days :-(

    Lessons learned

    Actually running into stuff like this is not all bad. Okay, granted: It is. I wasted too much time with it. But the good part is, that it’s just another lesson along the way. And a lesson I probably won’t forget that soon.

    For this day my takeaways were:

    • Do not trust messages of other apps
    • Do not rename packages without renaming logcat tags as well
    • Stop being so sloppy with your tests

    That’s it for today. The next post in this series will have the name “Be careful with that package name, Eugene”. Obviously it nicely fits the scheme of this post since it’s just another package name mishap.

    Have you experienced anything like that? If so, please let us know in the comments. Don’t let me be the only fool around :-)

    An XMPP Server for Google Cloud Messaging

    In this post I am going to write about the server-side of upstream messages with Google Cloud Messaging. This is the second part of my three-part series on this topic. If you haven’t read the first part about the flow of events and the Android implementation of upstream messaging, please read that one first. The first sections of that post are important to understand the big picture of upstream messaging and the role of the server within it.

    Sample project

    I have created a sample project for the server side of upstream messaging with Google Cloud Messaging. Please note that this is a sample. It’s not suitable for production!

    Permanent connection and XMPP

    Just recall the flow of events, described in detail in my first post:

    The communication model of Google Cloud Messaging with the new Cloud Connection Server

    The communication model of Google Cloud Messaging with the new GCM Cloud Connection Server

    For this flow to work, Google must contact your server whenever the user sends a message from his device upstream to Google’s cloud. There are many models of how to do that. The one chosen by Google is to require a permanent connection between your backend and one of Google’s endpoints.

    That’s where XMPP comes into play. Google has chosen XMPP as the protocol of choice for communicating between its servers and your server. Google named its XMPP endpoint “GCM Cloud Connection Server” or CCS for short. XMPP is an XML-based protocol that was created for instant messaging (also known under it’s original name Jabber). You can read more about XMPP on Wikipedia.

    Server side code

    In the previous post about upstream messaging you have seen that the Android side of GCM messaging is as simple as it can get.

    The server side though is another matter altogether and got more complicated with the new solution.

    First of all you’re most likely not as familiar with XMPP as you are with HTTP. And you’re not alone with it. HTTP is probably the most used application layer protocol. Thus the online knowledge base for HTTP is huge. Less so for XMPP. You probably have to search longer for solutions when hitting a stumbling block with XMPP.

    This situation also applies to libraries. While there is an abundance of HTTP libraries, there are way less for XMPP. For Java I have found only one library that is still actively maintained: The Smack library, which Google also uses in its sample code.

    Luckily Google has a very detailed description of all the message types exchanged between your server and Google’s cloud. And since XMPP is text-based you could build a client on your own – no matter which language you use. Nevertheless I recommend to use a library for this – after all they not only ease your life but are also more heavily tested. It’s likely that others already have found a solution for a problem that would otherwise bite you in production when writing your own code.

    I have taken Google’s sample code for XMPP and extended it to be more flexible and suit my needs. This code requires the Smack and the json-simple libraries. To repeat: The demo is there just to get you up and running, so that you can easily test the upstream messaging model and your Android code. It’s still very basic and rough!

    Logging messages

    When setting up the connection using Smack’s XMPPConnection, you can configure it to open a Swing window displaying all incoming and outgoing messages:

    config.setDebuggerEnabled(mDebuggable);
    

    I set the flag to true when using the main() method of CcsClient. That obviously wouldn’t work too well on a server so I made this configurable. From within my web project I set this flag to false.

    There is another flag that configures if Smack logs every message:

    XMPPConnection.DEBUG_ENABLED = true;
    

    Within the sample code I simply set this to true to see every message. Very handy for finding problems during development and appropriate for this demo project.

    Implementing a server

    These are the things you have to take care of:

    • Establish the connection
    • Authenticate your server app
    • Receive messages from Google’s cloud
    • Send messages to Google’s cloud
    • Acknowledge messages
    • Deal with problems

    Since all message types are described in detail on Google’s Cloud Connection Server page, you can use whatever solution you like. The following code samples are in Java and make use of the Smack library. While some stuff is from Google’s sample code, some contains additions and abstractions around that sample code.

    The most important class is CcsClient. This class is responsible for logging in to the server, sending messages to Google’s Cloud, receiving incoming messages and handling ACKs and NACKs correctly.

    Connect to the GCM Cloud Connection Server

    For the permanent connection you open a TLS secured connection to gcm.googleapis.com at port 5235.

    Within CcsClient the method connect() handles this. It needs a ConnectionConfiguration object.

    Here’s how to set up the ConnectionConfiguration:

    config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
    config.setSecurityMode(SecurityMode.required);
    config.setReconnectionAllowed(true);
    config.setRosterLoadedAtLogin(false);
    config.setSendPresence(false);
    config.setSocketFactory(SSLSocketFactory.getDefault());
    

    In the first line you specify which server and which port to use. As mentioned these have to be gcm.googleapis.com and 5235 respectively. And you have to ensure to use Transport Layer Security (TLS). That’s why you have to set the SSLSocketFactory.

    Afterwards you can create a Connection object and use it to establish the connection to Google’s servers:

    Connection connection = new XMPPConnection(config);
    connection.connect();
    

    Authenticate your server app

    Google needs to ensure that you are allowed to send messages via Google Cloud Messaging – and that you are allowed to send them to the clients you are addressing. For this Google uses a project id and an API key specific for that Google Cloud project.

    I have detailed in my previous post about upstream messaging how to create a project and how to generate a server API key for that project.

    With XMPP you do not send the API key with every request. Instead you authenticate your server app directly after establishing the connection.

    In Java just use the Connection object you created in the previous step to log in:

    connection.login(mProjectId + "@gcm.googleapis.com", mApiKey);
    

    Obviously you have to use the values created on Google’s Cloud Console for mProjectId and mApiKey. You either pass them as arguments to the main() method of CcsClient or you call prepareClient() with the correct values – which I do from within my web project.

    After logging in, you can send and receive messages.

    Message formats

    Before I will cover how to send or receive messages, I’m going to show you some typical messages sent either from your server or back to your server.

    Incoming upstream messages

    The following is a message as it shows up on your server when a user clicks “Register” in the Android client sample:

    <message 
          to="projectId@gcm.googleapis.com" 
          from="devices@gcm.googleapis.com">
       <gcm xmlns="google:mobile:data">
          {
          "category":"com.grokkingandroid.sampleapp.samples.gcm",
          "data":
             {
             "action":
                "com.grokkingandroid.sampleapp.samples.gcm.REGISTER",
             "account":"info@openminds.de"
             },
          "message_id":"20",
          "from":"someRegistrationId"
          }
       </gcm>
    </message>
    

    This message is no different from any other message sent from an Android device. It is obvious that the message consists of an outer XML part and an inner JSON part. You can safely ignore the XML part. It’s always the same and is only used since XMPP is an XML based protocol. What’s important is the JSON part. The JSON object contains all the attributes you need to react appropriately to incoming messages.

    All upstream messages contain the following attributes:

    The attributes of a received GCM upstream message
    Attribute Meaning
    category Package name of the sending app
    data The payload of your app
    message_id A unique id you need later on to acknowledge the message
    from The registration id of the device from which the message was sent

    Obviously only your apps can send data to your server. But you can use the same GCM server for multiple apps. That’s why the category attribute is needed.

    The data attribute is where you can put all the stuff, that you want to transmit to your server. The value of the data attribute is a JSON object itself.

    The registration id is sent with every message within the from attribute. It’s a very lengthy string which you must use to map the data to the correct user.

    ACK messages

    The next section explains what’s up with the ACK and NACK messages. For now, you just need to know what those messages look like.

    An ACK message is the simpler of both and always looks the same:

    <message>
       <gcm xmlns="google:mobile:data">
          {
          "message_id":"m-8238983812089683316",
          "message_type":"ack",
          "from":"someRegistrationId"
          }
       </gcm>
    </message>
    
    The attributes of an ACK message
    Attribute Meaning
    from The registration id to which the message was sent
    message_id The id of the message, that is acknowledged
    message_type ACK or NACK – for ACK messages obviously always “ack

    Incoming NACK messages

    NACK messages come in two types. A stanza message always indicates a malformed message on your side. Stanza is the weird name used in the XMPP specification for the different kinds of XML messages that XMPP supports. Any other erroneous condition is handled by the second type of NACK messages.

    Let me show you a stanza message first:

    <message 
          id="iUB3B-2" 
          to="someProjectId@gcm.googleapis.com" 
          type="error">
       <error 
             code="400" 
             type="MODIFY">
          <bad-request 
                xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
          <text 
                xml:lang="en" 
                xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">
                InvalidJson: JSON_PARSING_ERROR
                      : Missing Required Field: message_id
          </text>
       </error>
       <gcm xmlns="google:mobile:data">
          {
          "to":"someRegId",
          "delay_while_idle":true,
          "data":
             {
             "message":
                   "Simple sample sessage"
             },
          "time_to_live":120000
          }
       </gcm>
    </message>
    

    The error element of the XML message contains the description of what went wrong. And the gcm element contains the complete message you have sent to the server. The descriptive error message together with the full message causing the problem makes it really simple to understand what went wrong. In this case, the message_id is missing. I won’t go into detail for this type. You get those messages only, if you do not provide all mandatory attributes.

    Stanza error messages should only happen while developing your app. What might follow later on are other problem types. Here is a sample message for other failure situations:

    <message>
       <gcm xmlns="google:mobile:data">
          {
          "message_id":"m-4370299872608467243",
          "from":"invalidRegId",
          "error":"BAD_REGISTRATION",
          "message_type":"nack"
          }
       </gcm>
    </message>
    

    In this case the registration id you sent to Google’s server is invalid. Note: You will also get NACK messages for as long as your sign-up form hasn’t been processed by Google.


    The attributes of a NACK message
    Attribute Meaning
    error A short error message
    from The registration id to which the message was sent
    message_id The id of the message, that is acknowledged
    message_type ACK or NACK – for NACK messages obviously always “nack

    Outgoing messages to devices

    The final message type is a message from your server to an Android device:

    <message id="4icfN-5">
       <gcm xmlns="google:mobile:data">
          {
          "to":"someRegistrationId",
          "delay_while_idle":true,
          "data":
             {
             "message":"Test message to a registered device"
             },
          "message_id":"m-15",
          "time_to_live":10000
          }
       </gcm>
    </message>
    

    Some of the attributes for sending messages via the Cloud Connection Server are the same as with messages via Google’s HTTP server. Others though are new and still others are missing. The following table shows a list of all possible attributes for sending XMPP messages to a device.

    The attributes of a push message
    Attribute Meaning Mandatory
    collapse_key A key indicating that only the last message of this type should be sent to a device when it comes online again No
    data The payload of your app No
    delay_while_idle A flag indicating that messages should be kept on Google’s server if the device is inactive No
    message_id A unique id you need later when dealing with ACK and NACK messages Yes
    time_to_live The amount of time for which Google should keep the message around if the device is offline No
    to The registration id of the recipient Yes

    If you have used GCM in the past you will notice the to attribute. That’s the XMPP replacement for registration_ids. And in contrast to registration_ids you can send a message to only one user. Which means that for a broadcast you have to iterate over all registration ids. See Google’s documentation for details.

    The delay_while_idle attribute tells Google that it should not send a message when the client device is not active. A value of true means that messages are kept on Google’s server until the device is active again.

    The collapse_key probably needs some more explanation. If a device is offline you do not want it to get swamped with messages when it goes online again. Instead you can use the attribute collapse_key to ensure that only the last message for this key gets delivered to the app. But note: You can use only four collapse keys at the same time. The collapse_key applies to messages not delivered right away because of an delay_while_idle flag, but also to messages than cannot be delivered because the device isn’t connected at all.

    You might have noticed that the data attribute is optional. Now at first this might sound like a pointless exercise. Why send a message without any data in it? But it depends on the purpose of the message. You can use a GCM message as a tickle. To simply notify your app, that there’s new data on the server to download. Unless the app can download different types of data, an empty message would be enough. When such a message arrives, your app would try to contact your server and download what it has to know.

    If you do not set a time_to_live value, the default is used. The default currently is four weeks.

    Message acknowledgements

    The GCM Cloud Connection Server expects your server to acknowledge each and every method it sends to you. Google states explicitly that you should never send a NACK!

    Always having to acknowledge messages means you should be able to deal with those messages. Take care of exceptional conditions, that might come up at your end. Google will resend messages for which you fail to send an acknowledgement. So not acknowledging puts unnecessary burden on your server.

    Here’s what Google expects your server to adhere to:

    For each device message your app server receives from CCS, it needs to send an ACK message. It never needs to send a NACK message. If you don’t send an ACK for a message, CCS will just resend it.

    Source: https://developer.android.com/google/gcm/ccs.html

    Google sends back ACK or NACK messages for every message your backend sends towards Google’s cloud. Google obviously is allowed to send NACKs. A NACK coming from Google means that you did something wrong – most of the time at least. For example you will get NACK messages for trying to send messages to registration ids that aren’t valid anymore.

    Google will also send NACKs if the service is down or in case an “Internal Server Error” occurred. In the first case you should simply queue the message to resend it sometime later. In the second case though, you are a bit on your own. Most likely resending should be fine since most other cases are handled with other exception codes. So most likely it’s a problem on Google’s end – but you cannot know for sure. Maybe the problem is caused by the content of your message after all. It might be a good idea to add an internal retry counter which you decrease with every transmission. At the very least log those cases and have a look at them.

    Receive messages from Google’s cloud

    To handle incoming messages with Smack, you first have to register a PacketListener object with the Connection you created in the first step above. This object is responsible for all incoming traffic. See this slightly adapted version of Google’s code:

    connection.addPacketListener(new PacketListener() {
       @Override
       public void processPacket(Packet packet) {
          Message incomingMessage = (Message) packet;
          GcmPacketExtension gcmPacket =
                (GcmPacketExtension)incomingMessage
                      .getExtension(GCM_NAMESPACE);
          String json = gcmPacket.getJson();
          try {
             Map jsonMap =
                   (Map)JSONValue.parseWithException(json);
             
             handleMessage(jsonMap);
          } catch (ParseException e) {
             logger.log(Level.SEVERE, "Error parsing JSON " + json, e);
          } catch (Exception e) {
             logger.log(Level.SEVERE, "Couldn't send echo.", e);
          }
       }
    }, new PacketTypeFilter(Message.class));
    

    And handleMessage() looks like this:

    private void handleMessage(Map<String, Object> jsonMap) {
       // only present for "ack"/"nack" messages
       Object messageType = jsonMap.get("message_type");
       if (messageType == null) {
          // Normal upstream data message
          CcsMessage msg = getMessage(jsonMap);
          handleIncomingDataMessage(msg);
          // Send ACK to CCS
          String ack = createJsonAck(msg.getFrom(), msg.getMessageId());
          send(ack);
       } else if ("ack".equals(messageType.toString())) {
          // Process Ack
          handleAckReceipt(jsonMap);
       } else if ("nack".equals(messageType.toString())) {
          // Process Nack
          handleNackReceipt(jsonMap);
       } else {
          logger.log(Level.WARNING, "Unrecognized message type (%s)",
          messageType.toString());
       }
    }
    

    The PacketListener has just one method: processPackage() which takes a Packet as argument.

    A data package – that is an upstream message coming from a device – is then delegated to handleIncomingDataMessage(). For my sample project I have modified Google’s original code quite a bit. For one I use a CcsMessage object here that represents the incoming message.

    Next I use PayloadProcessors to deal with the different type of messages. For every possible type of message I have a specific implementation of this interface to actually deal with the incoming message. You can of course replace this logic with whatever suits you.

    What you do within those PayloadProcessors is very app-specific. The sample code just provides very basic implementations to give you an understanding of how to deal with messages. Hopefully your app has more to offer than my sample :-)

    Send messages to Google’s cloud

    To send a message to Google’s Cloud Connection Server, you have to follow these steps:

    1. Create the JSON payload
    2. Create a Smack Packet for the message
    3. Send the XML message to Google’s cloud

    Create the JSON payload

    With json-simple you can create a JSON object from is a map by calling JSONValue.toJSONString(). Each key of the map corresponds to one JSON attribute. In the section about message types I have listed the possible attributes. With this you can first create the map:

    public static Map createAttributeMap(
          String to, 
          String messageId, 
          Map<String, String> payload,
          String collapseKey, 
          Long timeToLive, 
          Boolean delayWhileIdle) {
       Map<String, Object> message =
             new HashMap<String, Object>();
       if (to != null) {
          message.put("to", to);
       }
       if (collapseKey != null) {
          message.put("collapse_key", collapseKey);
       }
       if (timeToLive != null) {
          message.put("time_to_live", timeToLive);
       }
       if (delayWhileIdle != null && delayWhileIdle) {
          message.put("delay_while_idle", true);
       }
       if (messageId != null) {
          message.put("message_id", messageId);
       }
       message.put("data", payload);
       return message;
    }
    

    Using this method creating a JSON string for sending a message is simple:

    public static String createJsonMessage(
          String to, 
          String messageId, 
          Map<String, String> payload,
          String collapseKey, 
          Long timeToLive, 
          Boolean delayWhileIdle) {
       return createJsonMessage(
             createAttributeMap(
                   to, 
                   messageId, 
                   payload,
                   collapseKey, 
                   timeToLive, 
                   delayWhileIdle));
    }
    
    public static String createJsonMessage(Map map) {
       return JSONValue.toJSONString(map);
    }
    

    Create a Smack Packet for the message

    Creating a Packet object is even simpler. Google’s code makes use of the extension mechanism of Smack. Smack’s extensions are handlers for specific message types. The code uses them for processing incoming as well as outgoing messages.

    Google’s inner class GcmPacketExtension is an implementation of Smack’s PacketExtension interface.

    It’s method toPacket() creates an XML Packet, in this case it wraps the JSON with appropriate XML as required by XMPP.

    Packet request = new GcmPacketExtension(jsonRequest).toPacket();
    

    Send the message to Google’s cloud

    If you have a Packet object you simply call send() on your XMPPConnection object that you created connecting to Google’s server in step one.

    My demo follows Google’s sample code in combining the last two steps in the method send() of the CcsClient class:

    public void send(String jsonRequest) {
       Packet request = new GcmPacketExtension(jsonRequest).toPacket();
       connection.sendPacket(request);
    }
    

    Sending to multiple recipients via Google’s Cloud Connection Server

    You cannot send a message to multiple recipients when using Google’s Cloud Connection Server. Instead you have to send one message for every registration id you want to send a message to. That’s why I added the message sendBroadcast() which simply iterates over all recipients:

    public void sendBroadcast(Map<String, String> payload, String collapseKey,
          long timeToLive, Boolean delayWhileIdle, List<String> recipients) {
       Map map = 
             createAttributeMap(null, null, payload, 
             collapseKey, timeToLive, delayWhileIdle);
       for (String toRegId: recipients) {
          String messageId = getRandomMessageId();
          map.put("message_id", messageId);
          map.put("to", toRegId);
          String jsonRequest = createJsonMessage(map);
          send(jsonRequest);
       }
    }
    

    Note: There actually is one option to target multitple registrations ids with just one message. With user specific messages you can target all devices of one user. But you’re still limited to one user only with this option. Since I’m going to cover user specific messages in my next post, I won’t deal with this option here.

    You can combine HTTP and XMPP

    Google allows you to use HTTP at the same time as XMPP to send messages to devices. It’s up to you if you want to use XMPP just to receive upstream messages of devices and to acknowledge those messages or if you want to use XMPP to talk to Google’s Cloud Connection Server (CCS) for everything.

    Actually there is one use case for which you have to use HTTP – at least at the moment. I very much hope that this will change when the final version of those new services is released for everyone. I will cover that specific use case next week.

    One final thing

    I have written most of the server code in preparation of my talk at the Dutch Android User Group meetup. As I have written in my previous post about Google Cloud Messaging, you have to sign up to use the new features like upstream messaging, XMPP or user notifications. After signing up, Google processes your request and some time later comes back with the approval. In my case the approval took a while and the preparation for the talk was in jeopardy.

    Gladly Dennis Geurts offered to use his testing API key and project id for which he had signed up much earlier. A big thanks for that, Dennis!

    Lessons learned

    With this post I have shown you some aspects of the server side of Google Cloud Messaging using the new upstream messaging model.

    You have seen the different message types, have heard of the need to acknowledge messages and how to receive and send messages using Smack’s Java library for XMPP. Since XMPP is text based those code snippets should be easy to transform to any other language.

    Together with the source of the demo project this post should get you on the right track to set up your own project.

    If you want to start using Google Cloud Messaging, be sure to read the official documentation. I couldn’t cover all in this post. Be sure to not forget the document about advanced topics. There is also a nice blog post by Ryan Oldenburg of Pushbullet about some thinks to keep in mind when using GCM. It might help you to avoid problems right away. For another perspective on the topic you might also want to read Antoine Campbell’s Cloud Connection Server Tutorial.

    One final problem: Right now I don’t know any SaaS or BaaS provider to support the XMPP messaging model for Google Cloud Messaging. This is a serious limitation in my opinion – one which I expect to get much better when this model gets adopted more often and is published to all without approval process. Should you know of any provider supporting the new GCM model, please drop me a line.

    Upstream Messages With Google Cloud Messaging

    Google announced a new messaging model with Google Cloud Messaging on last years Google IO. This model allows for upstream messaging and for user specific notifications. This post is the first in a three-part series in which I am going to look into both these changes and to show you how to use them.

    I had never written these posts if it weren’t for the Dutch Android User Group meetup in Utrecht (January 2014), where I had the pleasure to talk about this topic. This event was well-attended and was packed with interesting talks about the changes in Android 4.4 and Google Play Services. If you have ever the chance to attend a meetup of our Dutch colleagues, I strongly suggest to do so. It has been a gorgeous evening and was well worth the two-hour drive. It was not just the talks but also the overall atmosphere as well as the conversations during the breaks and afterwards. A big thanks to the organizers for the awesome evening!

    You can find my slides on the speakerdeck site. And a video of the talk should also be available pretty soon.

    Sample App

    I have published sample apps on github where you can see how to use this in context. For the Android client clone the gcm_sample project. For the server clone the gcm_server project.

    What’s new

    With Google Play Services 3.1 Google made some changes to Google Cloud Messaging:

    • You can send messages upstream from the user’s device
    • You have to use a permanent connection between your backend and Google’s services
    • You can use user specific notifications

    In this post I will only cover upstream messaging. That is the flow of events and what to do on Android’s side. In my next post I’m going to cover the server side – and in the third post I will write about user specific notifications. User notifications allow you to send user specific messages with the possibility to cancel notifications on other devices if they have been consumed already on one device.

    Upstream messaging

    With the new GCM release Google allows you to send messages directly back to Google’s cloud. That’s what they call upstream messaging. Have a look at the following diagrams. The first one is the traditional model of Google Cloud Messaging while the second one shows the new flow of events.

    The classic communication flow with Google Cloud messaging

    The classic communication flow with Google Cloud messaging


    The communication model of Google Cloud Messaging with the new Cloud Connection Server

    The communication model of Google Cloud Messaging with the new Cloud Connection Server

    The first two steps in both diagrams are the same: You tell the Google Cloud Messaging API that you want to register a device (step 1). If the registration succeeds Google returns the registration id for this device (step 2).

    Traditionally you would then send the registration id back to your server (step 3). The protocol was up to you but very likely HTTP. The server would (hopefully) respond with a success message (step 4).

    From then on your server could send messages to Google’s Cloud Messaging service (step 5) and the user’s device would receive it, if it’s registration id was part of the registration_ids parameter of the message (step 6).

    With upstream messaging though your app would send the registration id (step 3) not directly to your server, but instead call a method of the Google Play Services API. Google Play Services would then send the message to Google’s servers.

    Google then processes the message and sends it to your backend. Obviously for this to work your backend must be connected in some way to Google’s cloud. I will deal with this part in my next post. For now it’s enough to know that there has to be a permanent connection between your backend and Google’s cloud and that Google will deliver messages that way (step 4).

    After the registration id has been transmitted successfully you can send messages to the device (step 5). But with the new way to use Google Cloud Messaging you would use the existing connection between your server and Google’s servers and use a different protocol (with slightly different parameters).

    Note that Google uses different names for its servers depending on which transmission model you want to use. Google uses the name “GCM HTTP Connection Server” for those servers receiving HTTP messages and it uses “GCM Cloud Connection Server” for those receiving XMPP messages via the permanent connection. The abbreviation CCS is very commonly used within GCM’s documentation.

    Create your credentials

    If you already use Google Cloud Messaging you can skip this part and proceed to the next section.

    If you’re new to Google Cloud Messaging, you have to create an API key in Google’s Cloud Console/Google Developer Console. Do not confuse it with the Google Play Developer Console. Both are unrelated.

    After logging in to the Cloud Console you will see a list of projects. Simply create a new one and give it a name and a project id in the next dialog. Now this could be a source of confusion. The project id you use here is not the project id you have to use in your code later on. It’s just a name which nevertheless has to be unique.

    Afterwards creating the project the developer console will show you the project’s page. Go to “APIs & Auth” in the menu and turn on “Google Cloud Messaging for Android” in the huge list of Google’s services. Since Google displays all your active services at the top, the entry will move directly to the top after you enable it. Don’t be irritated by that tiny UX glitch. Simply scroll to the top and you will see that it’s status has changed to “On”. That’s great.

    Switch to Credentials in the menu on the left. At the top of the new screen you can find a client id. It starts with a number followed by “.apps.googleusercontent.com”. Select the number (only the number), copy it and paste it into your strings.xml – or a special gcm_strings.xml that only contains the project id. Name the string whatever you like – in the sample project I expect a string named gcm_project_id.

    That’s all you need for the Android part. But since you’re logged in to the dev console anyway, let me show you how to create the API key for your server right away.

    Go back to the dev console. On the Credentials page there are two sections. The OAuth section on the top is where you have found the project id. Below of it is the section called “Public API access”. It’s still empty. Click “Create New Key” and in the next dialog select “Server key”. Afterwards you will see the API key for server applications together with some additional information. You will use the API key when following my post about the server side of GCM.

    Sign up for using the new features

    To be able to use all the shiny new features of Google Cloud Messaging, you have to sign up first. With the sign up form you “Sign up to be a trial partner”. The new services are not yet finalized. It’s a bit like it has been with Google Cloud to Device Messaging (C2DM) – the predecessor to GCM. You had to sign up as well, and when the service was finally made public, it had evolved to Google Cloud Messaging. So expect the API to change!

    Using Google Play Services

    You need to use Google Play Services from within your app for registering the device for as well as for sending upstream messages.

    Setting up Google Play Services is easy, but requires too many steps to cover them in this post. And those steps also are different depending on whether you use Android Studio, Eclipse or something else. Have a look at the Play services documentation if it’s the first time you use Google Play Services.

    The very first step in your code when using Google Play Services is to make sure that Google Play Services are available at all. You can do so with the following snippet:

    private boolean checkPlayServices() {
       int resultCode = 
             GooglePlayServicesUtil
                .isGooglePlayServicesAvailable(getActivity());
       if (resultCode != ConnectionResult.SUCCESS) {
          if (GooglePlayServicesUtil.
                isUserRecoverableError(resultCode)) {
             GooglePlayServicesUtil.getErrorDialog(
                   resultCode, 
                   getActivity(),
                   RC_RES_REQUEST).show();
          } else {
             Log.i("grokkingandroid", 
                   "This device is not supported.");
          }
          return false;
       }
       return true;
    }
    

    What to do when the services are not available, depends on how important they are for your app. If Play Services are not essential, I suggest to let the user know – but in an unobtrusive way. After all the app is usable without it, so do not annoy your users with dialogs or other stuff that keeps them from doing what they actually installed the app for.

    Registering the device for Google Cloud Messaging

    The next step is to register the device. Google needs to know about your device before your app is allowed to receive or send messages.

    In my sample app the user has to explicitly click the button register. Not a typical use case, but for the sample this makes sense. Now when to do this is in a real app is up to you. But when your app benefits from Google Cloud Messaging you usually want to register the device as soon as possible.

    I also let the user select a Google account. Your app’s users do not need one for Google Cloud Messaging. I solely request one to use this account for user specific notifications. I will cover those in the third post of this series.

    Registering actually is very easy. First get hold of a GoogleCloudMessaging object and then simply call its method register() passing in the project id of the dev console (see “Create your credentials” above):

    String projectId = 
          getResources().getString(R.string.gcm_project_id);
    GoogleCloudMessaging gcm = 
          GoogleCloudMessaging.getInstance(this);
    String regid = gcm.register(projectId);
    

    Be careful though: Asking for the registration id is a blocking request. Hence, you should always use the call in a separate thread off the main thread (UI thread). In the sample project I am using an IntentService to achieve this.

    Send messages upstream

    As soon as the device is registered, it can send messages upstream – as well as receive messages. Probably the very first message to send upstream is the newly received registration id.

    Sending messages is nearly as simple as registering. You create a Bundle with all the payload data you want to transmit and you also have to create a unique message id. In my sample code I simply increase a counter I keep within the SharedPreferences for the message id. Depending on your payload the code might look more or less like this:

    try {
       Bundle data = new Bundle();
       // the account is used for keeping 
       // track of user notifications
       data.putString("account", account);
       // the action is used to distinguish 
       // different message types on the server
       data.putString("action", Constants.ACTION_REGISTER);
       String msgId = Integer.toString(getNextMsgId());
       gcm.send(projectId + "@gcm.googleapis.com", msgId,
             Constants.GCM_DEFAULT_TTL, data);
    } catch (IOException e) {
       Log.e("grokkingandroid",
             "IOException while sending registration id", e);
    }
    

    As you can see you once again need a GoogleClientMessaging object and call its send() message.

    This message takes as parameters the project id appended with the fixed string “@gcm.googleapis.com“, a unique message id, a time to live value and the bundle with your payload.

    You might notice that I do not include the registration id as part of the payload. That’s because Google Play Services adds the registration id to every message to your backend anyway. You will see in the next post which parameter Google uses for the registration id. For now, just keep in mind that above code is all that is actually needed.

    Those strings within the bundle are not even necessary. I use the account because I want to send user specific messages and I use the action to differentiate on my server between different message types.

    As you can see there is no special message for sending the registration id back home. It’s just a message like any other upstream message.

    Benefits of Upstream messaging

    Now that you know how to send upstream messages, you might wonder about why to use upstream messaging in the first place. Why not send your message back to your server as you always did (assuming you did contact your server)?

    There are three reasons on the Android side for using the new model:

    • The upstream messaging API is dead simple
    • Upstream messages can reuse connections
    • Upstream messages are needed for notification cancellation

    The API is dead simple

    You have seen how simple the Android code is. It’s just some message calls to Google Play Services’s GoogleCloudMessaging class. It’s really just this one class, which with only six public methods is not too difficult to grasp :-)

    Contrast that with using HTTP instead: When talking back to your own servers directly you have to take care of checking if the network is available, send off the message, check for any error conditions and enqueue the message for later delivery if anything goes awry. All in all you’re better of with upstream messaging – at least for as long as you only care about the Android code.

    Upstream messages can reuse connections

    Not only is the API easier to use, it can also save resources. The user’s device has a connection to Google anyway so with upstream messaging Google Play Services can reuse this connection. The services take care of using the most power efficient way to send messages so you do not have to deal with that. This helps keeping the battery usage of your app to a minimum.

    Of course if your app only sends messages every once in a while, your users won’t notice any change in the battery usage. But if your app has to send many messages to your backend, this might make a difference to your users.

    Upstream messages are needed for notification cancellation

    The strongest argument for using upstream messaging though is notification cancellation. If you send messages from your server to specific users, you do not want them to see a notification on each and every device – even if it has long been read on another device. I will deal with user specific messages and notification cancellation in my third post about Google Cloud Messaging. So stay tuned :-)

    Permissions

    To use Google Cloud Messaging you need quite a lot of permissions:

    <uses-permission 
       android:name="android.permission.INTERNET" />
    <uses-permission 
       android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission 
       android:name="android.permission.WAKE_LOCK" />
    <uses-permission 
       android:name="com.google.android.c2dm.permission.RECEIVE" />
    <permission 
       android:name=
          "com.grokkingandroid.sampleapp.samples.notifications.gcm.permission.C2D_MESSAGE"
       android:protectionLevel="signature" />
    <uses-permission 
       android:name=
          "com.grokkingandroid.sampleapp.samples.notifications.gcm.permission.C2D_MESSAGE" />
    

    The first three are predefined permissions. You might notice the account permission. Actually this one is only needed for API levels before Android 4.0.4. I added it for completeness.

    The fourth is a bit of an oddity. It’s the old Cloud to Device Messaging (C2DM) permission. For backwards compatibility it makes sense to not change it – otherwise existing apps had to ask for a new permission. But it looks weird about two years after C2DM was deprecated.

    You also have to create a new permission of your own. That’s the permission that ensures that no other app can receive messages intended for your app. It has to exactly follow this naming convention: Package name plus “.permission.C2D_MESSAGE“. Otherwise your app won’t receive the messages sent to it. Your app also must use this newly created permission.

    Receiving messages

    Of course the fun part of Google Cloud Messaging is to actually receive push messages from the cloud. Google transmits the messages to your app to a BroadcastReceiver.

    The following code is basically the same as Google’s sample code on their client page:

    /**
     * See http://developer.android.com/google/gcm/client.html
     */
    public class GcmBroadcastReceiver 
          extends WakefulBroadcastReceiver {
       @Override
       public void onReceive(Context context, Intent intent) {
          // Explicitly specify that
          // GcmIntentService will handle the intent.
          ComponentName comp = 
                new ComponentName(
                   context.getPackageName(),
                   GcmIntentService.class.getName());
          // Start the service, keeping the 
          // device awake while it is launching.
          startWakefulService(
                context, 
                (intent.setComponent(comp)));
          setResultCode(Activity.RESULT_OK);
       }
    }
    

    The Broadcastreceiver gets the message – but since it runs on the UI thread it should immediately pass the message on to some background thread. I use the same IntentService you have already seen for registering the device.

    Actually parsing the message and doing what has to be done is done in the service. Again The code is pretty much the same as on Google’s documentation:

    // handling of stuff as described on
    // http://developer.android.com/google/gcm/client.html
    try {
       Bundle extras = intent.getExtras();
       // The getMessageType() intent parameter
       // must be the intent you
       // received in your BroadcastReceiver.
       String messageType = gcm.getMessageType(intent);
       
       if (extras != null && !extras.isEmpty()) {
          /*
          * Filter messages based on message type. 
          * Since it is likely that GCM will be 
          * extended in the future with new 
          * message types, just ignore any message 
          * types you're not interested in, or that you
          * don't recognize.
          */
          if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
                .equals(messageType)) {
             sendNotification(
                "Send error: " + extras.toString());
          } 
          else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
                .equals(messageType)) {
             sendNotification("Deleted messages on server: "
                + extras.toString());
          } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
                .equals(messageType)) {
             // Post notification of received message.
             String msg = extras.getString("message");
             if (TextUtils.isEmpty(msg)) {
                msg = "empty message";
             }
             sendNotification(msg);
          }
       }
    } finally {
       // Release the wake lock provided by the WakefulBroadcastReceiver.
       GcmBroadcastReceiver.completeWakefulIntent(intent);
    }
    

    As you can see GCM uses different message types. the last one is the one actually containing a new messages. The first one informs you about errors when sending messages and the second tells you that messages have been deleted. If for example you display incoming messages with a notification you would have to cancel the notification in this case.

    What to do when receiving an actual message is very specific to your app. The sample app simply displays a notification.

    Do not forget to release the wake lock. That’s the line within the finally block. The finally block ensure that this call will always be done – even if any exception has been thrown in the code within the try block. Be sure to do it that way!

    Lessons learned

    In this post you have seen how the message flow has changed when using Google Cloud Messaging. With the previous model you had to contact your server directly from the device, now you only tell Google Play Services what to do with the new upstream messaging model. Google’s services take care of actually delivering the message to your server.

    You also have learned about how to set up the project in Google’s developer console and that you have to sign in to use the new features.

    Finally you have seen how easy the Android code actually is and what the benefits of upstream messages are.

    In the next post you will learn more about the server side of upstream messaging – which is a tad more complex. And after that I’m going to show you how to use user notifications in the final post of this series.

    Chrome-Apps on mobile devices – a good idea?

    Google announced a new set of tools this week to help developers publish their Chrome apps on iOS and Android. That’s the next logical step by Google to win over more developers for Chrome apps. In September Google already announced that from then on developers could publish their Chrome apps as offline apps, allowing users to use them like any other desktop application. Those offline apps from now on can also be published on iOS and Android. BTW: It’s interesting that Windows Phone is no target platform for Chrome apps and hasn’t even been mentioned on the blog post.

    To make this work, Chrome apps have to use a thin wrapper to be considered a “native” app and to access phone functions not available via HTML 5 as of yet. For this Google uses Apache Cordova, better known as Phonegap. With the help of this project and further additions made by Google, Chrome apps can be published on Google Play and Apple’s App Store. You can read more about it on Google’s blog post.

    Users cannot recognize those apps as Chrome apps in the respective app stores. They just show up as any other app. And that’s where the problem starts.

    Taking a web app, which works fine on a desktop, wrapping it with some tools and publishing it, that’s just not enough. Those apps would fall short of users’ expectations.

    First of all those apps would look totally out of place. Just have a look at this screenshot of Google’s blog post:

    Screenshot of one of Google's sample apps

    Screenshot of one of Google’s sample apps

    There’s no action bar, those buttons look weird, the header is very unusual – it just doesn’t fit. Of course you could get around most problems and make it look properly – but that would require some additional work. You would no longer just wrap an existing app, but start to provide platform specific deviations to achieve proper designs.

    Secondly interaction patterns on the web, on desktop apps and on mobile apps are totally different. Consider the differences between iOS and Android alone. Tons of difference like navigation patterns, action placements, list treatment and so on. This problem is much worse and has much more influence on whether an app feels like a properly done app or not. And no cross-platform tool can help you with that. You will end up with multiple versions for all supported platforms anyway. Just consider the code. You probably can structure this in a way that is maintainable – but not if the main reason for taking this route was saving costs in the first place.

    Third I wonder about the quality of the apps. This is a very personal fear based on my experience with Firefox OS apps. Those are very often normal desktop apps as well – which too often do not work on a mobile device. It might happen, that desktop app developers simply wrap up their app and do neither test properly nor know about those limitations. Of course those apps would get ratings that bad, that they wouldn’t show up for most searches anyway. But Google is setting expectations for devs here – and those devs might be very disappointed down the road.

    As you’ve seen there are plenty of issues with the user experience. But obviously technical issues exist as well.

    It seems that it’s not that easy from a technical point of view as Google makes us believe it is. Just have a look at the sample apps. Five (!) of those 17 apps do not run on Android at all. Another six only with limitations. Or put it another way: Only one third of those apps works properly on Android. For iOS it’s about the same (though with different apps): Six apps don’t work at all, another five only with limitations. Only two out of 17 apps work properly on both supported platforms! And this is about to help devs? This should be a proper way to develop cross-platform apps? Not at all!

    The only thing that I am confident to work properly is the responsiveness of those apps. Web developers do that for years. They understand and grok responsiveness.

    If you want to publish apps and want your users to like your apps, you have to take the patterns and specifics of each platform into consideration. That means work. No matter which approach you choose. I guess that the total amount of work is even less if you design and develop different apps for Android, iOS, Windows Phone and (hopefully) Firefox OS than when you try to use a cross-platform tool. And I have yet to see a cross-platform app that actually does work properly on different platforms.

    Google has done so much in recent years to consolidate the design, interaction patterns and overall usability of Android. Which makes the recent announcement all the more disappointing. It’s a step backwards. It’s going back to where we were some years ago: A world without a unified design language without common interaction patterns. I do not want this. And I strongly believe, users do not want this as well.

    As a developer you have to keep an eye on this project. At least because your clients might mention it. But it’s not working. At least not yet. If it ever will – I do not know.

    Project managers and product managers should also carefully consider the limitations of this approach. Don’t think it will save you money! Don’t think it will save you time! If you’re not careful and use it without proper analysis, you’re bound to see costs rising unexpectantly (well, actually that’s to be expected) and your users will still rate your app poorly.

    Note: This post has initially been written for the German publication computerwoche.de.

    FirefoxOS – my Initial Impression

    Quite a while ago I ordered a Peak+ FirefoxOS phone at geeksphone.com. Alas after some delay it finally was cancelled – so I settled for the smaller version, the normal Peak. About a week or two ago it finally was delivered. After some very short initial testing I had more pressing things to do. But this week I gave it another look. Here are my initial impressions – mostly of FirefoxOS and less of the Peak itself.

    The phone itself

    I was quite suprised by the size of the device. It’s roughly the same as the N5 – though the screen is much smaller and the screen resolution even more so. That’s not so good – but it’s a dev phone, so it’s not really that important. But for any handset maker out there: If your screen doesn’t provide the resolutions current top devices spout, please make your device smaller.

    Of course the phone is plastic all around – it’s after all a cheap phone. I do not mind. I never thought, that plastic feels cheap. Actually I prefer plastic over metal or – even worse – glass. So it feels quite good – albeit a tiny bit too large. Some rubberized finish would be a nice addition, though.

    The screen is surprisingly good. Of course the resolution is far away from those of top device, but mostly good enough. Only for screens with much text, the resolution is an issue.

    The camera of course isn’t great – but for simple snapshots it should be sufficient. You won’t ever win a price with those pictures though.

    Battery life: Seems to be good, very good indeed. But that’s just an initial impression. I have yet to make the phone my primary device for a few days. Something I am not quite ready to do so, yet. You will see in the next section, why not.

    UX issues

    FirefoxOS is full of UX issues. I’m a developer and definitely no UX expert. But even I can spot many problems. Users will notice, will stumble upon those issues and think that something’s not right. So in my opinion, Mozilla should concentrate on those issues – especially some stuff that from an outside perspective looks like something that should be easy to fix. Of course I know that this outside perspective is often misleading, but hopefully some issues are easy to fix.

    Touch feedback is rare. Which is a deadly sin for a touch based interface. Take the Action Bar (in FirefoxOS slang it’s the Header). When I hit back in the top left corner, I want to see the back indicator highlighted. But that’s not happening. So did I touch it? Should I touch again? And it’s not just in the FirefoxOS Header.

    Missing touch feedback is sometimes made worse by a lacking loading indicator. I want to see a spinning wheel or some other indicator that content is loading – let me know that you do something. I hit back twice over and over because I had no feedback whatsoever.

    Firefox Marketplace app lacks touch feedback as well as loading indicators all over the place. And the app doesn’t seem to cache anything. It feels like the app reloads all lists whenever I go back to them. That slows things down considerably and make missing feedback even worse.

    The next issue might partially be based on my Android experience. But whatever the reason: I miss the back button dearly. I’m not using “up” often on android and having to go up to the Header/Action Bar feels very weird. But it’s not only uncomfortable, it’s sometimes even problematic. What to do on with an information dialog? I happened to stumble upon that at least once. Granted, it’s the fault of the app, but nevertheless a problem that could be hurting the OS adption.

    The lock screen is also a UX fail. You first have to pull up a bar from the bottom – which is nicely indicated by an appropriate animation. But afterwards you have to do another step: You have to click on the unlock icon. Two steps to unlock the phone? That’s one step too much. As simple as that!

    The list of opened apps also has a problem. There’s a button to close this app – which works more or less randomly. Swiping the app away, though, works fine all the time.

    I had some trouble with flinging through lists. One problem: When flinging repeatedly in long lists, the flow stops. Don’t know how to describe this correctly. But the new movement of my finger stops the last one and starts a new fling. That feels very unnatural. It doesn’t feel like a continuing movement.

    Another one is the notifications drawer. You have to drag it all the way down to see the top most notification. Which is bad if you just want to peek at the notification. It feels totally strange to have to scroll that far to finally see the one notification that caused you to use the notification drawer in the first place.

    The on screen keyboard also feels kind of weird to me. Cannot exactly nail it, but it just doesn’t feel right. Of course on Android I swipe most of the time, but it’s not just that. The spacing between keys is very narrow, but I guess that isn’t it either. Hopefully I can tell you in a follow-up post, what it is that actually bothers me. Right now it’s just the feeling: This is not right. The only thinkg, I can tell you for sure, is the surprising location of the “‘”. It’s right next to the letter “l” and directly above the return key. I accidentally hit it way too often.

    Apps

    The general quality of the app is not great – to say the least.

    One example: Pulse as one of the top apps promoted in the news category. When starting Pulse for the first time, the first thing you see, is the suggestion to get the app! WTF! I do not know about the reason, but my guess is, that this Pulse “app” is simply the mobile website. Don’t know if this is Pulse’s fault or Mozilla’s fault, but it sheds a bad light on the platform. This shouldn’t happen. This mustn’t happen!

    Next I downloaded a Pomodoro timer and a kitchen timer. Neither of these works when the OS goes into sleep mode. What? A timer not ringing, when the screen turns off? These seem to be apps for a desktop firefox. If they do not work properly on FirefoxOS, those apps shouldn’t be available in the marketplace on these devices. Some quality assurance must take care of that. I actually found not one timer app that deals with this correctly.

    Another example is the stock Camera app. When taking a photo and viewing it from within the Camera app, I sometimes got a black screen when enlarging the picture. Initially I thought the app just crashed (or run into some endless loop), but all buttons were still visible and reacted properly. Actuall it’s just that the screen remains black until the enlarged picture is ready to be displayed. Which can last an astonishingly long time. This is a horrible user experience – just show me some blown up but undetailed preview of the area and display more details progressively.

    The Marketplace app itself has problems. I do not want to see many apps, I want to see quality apps. One timer would be enough if it works properly and has at least a decent usability. But about ten timers and none working as expected, that’s about as useful as no timer at all. I also do not need all soccer leagues of the world. I want to find the one local to me (granted, some leagues might be more interesting to others worldwide than others, but I gues most people want to see the league of their home country). Same goes for news and anything else. I am still asztonished that Google doesn’t provie a better search experience on Google Play, but now I can appreciate what they have been doing. Definitely the results are more relevant than thos in Firefox market place.

    Importing stuff

    As an Android user I obviously have stuff on Google’s server. My contacts, my calendar, mail, what not. I was able to import contacts flawlessly, but strangely enough I couldn’t import any calendar information. No error dialog, it simply stopped after I entered all credentials. This is crucial and could be a big issue for FirefoxOS.

    And since we’re at it: A central account setting makes life so much easier. That’s something Android does very well. Not just for Google accounts, mind you. But for any apps that make use of sync adapters and authenticators. It’s cumbersome to have to enter the credentials over and over again because there isn’t such a central place in FirefoxOS.

    Initial verdict

    Boy, Mozilla has still a lot to do. I still very much hope for FirefoxOS to succeed. That’s why I ordered the phone in the first place. I love Android but Android needs another viable open competitor. Microsoft and Apple obviously do not fit that description.

    But to be competitive in the market place, there is still much to do for Mozilla and app devs developing for FirefoxOS.

    Then Mozilla needs to adress the usability issues. There are probably many more I didn’t even notice. But that’s what makes users recommend a system if done right. If done wrong, though, users most probably will advise against buying it. Shouldn’t happen.

    And of course we do need more apps. For this FirefoxOS has to gain more traction. The usual catch-22 situation of all the follow-up systems in the mobile space. That’s something we all can contribute to. If you want FirefoxOS to succeeed, help Mozilla out wth an app or two :-)

    Of course all is open source, so if you want to do so you can also help with all the other issues, I mentioned. Mozilla probably would be very happy about any new contributors to the platform.

    This all sounds pretty dim. But you have to consider that it’s only an initial impression. Then version 1.2 is in the making and might (hopefully) correct many of the issues. I personally still have hope for the platform. So much actually that I’m giving development for it a try and to publish an app myself. I will let you know about this in a future post. But: This is still an Android centric blog. FirefoxOS related posts will only be sparse in between.

    Let me know what you think and what your experience with FirefoxOS has been.

    Migrating from ActionBarSherlock to ActionBarCompat

    In July 2013 Google announced ActionBarCompat as part of its support library package. This library makes it easy to use the Action Bar that have to support older devices. Many have waited for this to happen ever since the Action Bar was introduced with Honeycomb.

    I, though, didn’t expect that to happen. After all the Action Bar was announced long ago and we had ActionBarSherlock. So why all off a sudden?

    I have written multiple posts about ActionBarSherlock on this blog prior to this announcement. Those posts still get a lot of attention and search hits. But while the basic concepts still apply, any ActionBarSherloc specific parts are kind of deprecated :-)

    I strongly believe that you should use ActionBarCompat for all new projects that want to support older devices. It also might make sense to migrate existing projects. So read on to learn why you should migrate or use ActionBarCompat right away and how to migrate existing projects.

    Why you should prefer ActionBarCompat over ActionBarSherlock

    There are many reasons why you should prefer ActionbarCompat over ActionbarSherlock.

    First of all this project is by Google, is part of the Support Library and thus likely will support new Action Bar related stuff at the same time Google releases them with stock Android.

    Another good reason and a proof for the previous point is that ActionBarCompat supports the Navigation Drawer pattern right out of the box, while ActionBarSherlock does not. Thus if you want to add this drawer to an existing project/app you should migrate.

    The last and not least reason is, that the creator of ActionBarSherlock, Jake Wharton, announced on Google+ that further development of ActionBarSherlock has been stopped. ActionBarSherlock 4.4 is the last release and might get bug fixes – but there won’t be any new features:

    While there may be a dot release or two in the coming weeks, version 4.4 is shaping up to be The Last Releaseâ„¢.

    He’s not too sad either :-)  See this quote, Jake Wharton made on his blog about ActionBarSherlock being intended to be thrown away eventually:

    This is the entire purpose of the library. It has been designed for this use case specifically. It has been deprecated from inception with the intention that you could some day throw it away.

    Sample project

    To showcase how the migration works, I have migrated the sample project ActionViews to ActionBarCompat. This sample project shows how to use the Action Bar with older devices and as a special case how to use ActionViews within your Action Bar. You can find more information about ActionViews on my older post. While originally written with ActionBarSherlock in mind, you can easily transfer those code samples to ActionBarSherlock. The next sections show you how to adapt the code snippets to move from ActionBarSherlock to ActionBarCompat.

    You can find the ActionViews sample project on bitbucket. If you like you can see all changes necessary for the ActionBarCompat migration by viewing the commit.

    Of course you have to integrate ActionBarCompat in the IDE of your choice. I do not cover this here. Gabriele Mariotti has written an excellent post covering the IDE integration of ActionBarCompat. I originally developed this project using Eclipse – which is why I occasionally refer to Eclipse specific shortcuts or why I include an Eclipse dialog later on. But the core of this post is independent of the IDE you want to use.

    How to proceed

    So I assume that you have removed ActionBarSherlock from the ActionViews project and added ActionBarCompat instead. After that your project should be plagued with errors. Which is not too surpising. In the next sections I will take you through all the steps needed to get the project deployable again.

    I start with the resources and deal with code changes later on. Android’s Development Tools only generate a new R.java file when the resources are error-free. And without a correct R file your Java sources won’t compile properly. Thus I prefer to fix resources first.

    Changing the style

    The first thing to do, is to correct the style. I have used an ActionBarSherlock style previously. This style has to change to the proper ActionBarCompat style. And as with ActionBarSherlock you have to use an ActionBarCompat style, otherwise you’ll get a RuntimeException at app start.

    Change the style with the name AppBaseTheme to use Theme.AppCompat.Light.DarkActionBar as its parent:

    <style name="AppBaseTheme" 
          parent="@style/Theme.AppCompat.Light.DarkActionBar">
       <!-- nothing API level dependent yet -->
    </style>
    

    Since you might forget this step in future projects – at least I’m prone to initially forget this step – here’s the Exception that you will see in logcat in that case. Having seen it here might help you to remember what to do about it.

    E/AndroidRuntime( 1413): Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
    E/AndroidRuntime( 1413): 	at android.support.v7.app.ActionBarActivityDelegate.onCreate(ActionBarActivityDelegate.java:111)
    E/AndroidRuntime( 1413): 	at android.support.v7.app.ActionBarActivityDelegateICS.onCreate(ActionBarActivityDelegateICS.java:58)
    E/AndroidRuntime( 1413): 	at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:98)
    E/AndroidRuntime( 1413): 	at com.grokkingandroid.sampleapp.samples.actionbar.actionviews.BaseActivity.onCreate(BaseActivity.java:30)

    The dev tools will highlight the attribute android:textIsSelectable somewhere up in the file after you save it. That’s because the minimum API level of the project is SDK 7 and the attribute has only been introduced with SDK 11. You can safely ignore this. If you clean your project after some more fixes, this marker will disappear. You won’t get any problems with lower versions despite this.

    Fixing the menu definitions

    The next step is to correct the menu definition files. Older Android versions don’t know about the Action Bar and thus do not support those new xml attributes for the Action Bar. So you have to change all attributes with the name android:showAsAction, android:actionViewClass, android:actionProviderClass, or android:actionLayout. The fix is easy. Simply change the namespace from android to app and add this namespace.

    For example for the file menu_fragment_expandable.xml the new xml looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item
            android:id=
               "@+id/actionViewLayout"
            app:actionLayout=
               "@layout/expandable_actionview_edittext"
            android:icon=
               "@drawable/ic_action_add_inverse"
            app:showAsAction=
               "ifRoom|collapseActionView"
            android:title=
               "@string/add_item"/>
    </menu>
    

    I make the namespace known to the parser in line 3. I use this namespace for the Action Bar specific attributes in lines 6 and 8. This way ActionBarCompat can read those attributes and provide the correct appearance of the menu items.

    Fixing the Searchview to use

    Have a look at the menu_fragment_search.xml file. Neither your IDE nor Android’s Lint checker will flag this file as incorrect. Yet it is.

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto">
       <item
          android:id=
             "@+id/searchView"
          app:actionViewClass=
             "com.actionbarsherlock.widget.SearchView"
          android:icon=
             "@drawable/ic_action_search_inverse"
          app:showAsAction=
             "ifRoom|collapseActionView"
          android:title=
             "@string/search"/>
    </menu>
    

    Obviously line 7 won’t work any longer. Instead of Sherlock’s SearchView you have to use the SearchView of the ActionBarCompat library. You now have to use the class android.support.v7.widget.SearchView. The updated file should look like this:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto">
       <item
          android:id=
             "@+id/searchView"
          app:actionViewClass=
             "android.support.v7.widget.SearchView"
          android:icon=
             "@drawable/ic_action_search_inverse"
          app:showAsAction=
             "ifRoom|collapseActionView"
          android:title=
             "@string/search"/>
    </menu>
    

    Should you forget this step in a project of yours, you are going to see an exception in logcat:

    W/SupportMenuInflater( 1308): Cannot instantiate class: com.actionbarsherlock.widget.SearchView
    W/SupportMenuInflater( 1308): java.lang.ClassNotFoundException: Didn't find class "com.actionbarsherlock.widget.SearchView" on path: DexPathList[[zip file "/data/app/com.grokkingandroid.sampleapp.samples.actionbar.actionviews-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.grokkingandroid.sampleapp.samples.actionbar.actionviews-2, /system/lib]]
    W/SupportMenuInflater( 1308): 	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
    W/SupportMenuInflater( 1308): 	at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
    W/SupportMenuInflater( 1308): 	at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
    W/SupportMenuInflater( 1308): 	at android.support.v7.internal.view.SupportMenuInflater$MenuState.newInstance(SupportMenuInflater.java:480)
    W/SupportMenuInflater( 1308): 	at android.support.v7.internal.view.SupportMenuInflater$MenuState.setItem(SupportMenuInflater.java:441)
    W/SupportMenuInflater( 1308): 	at android.support.v7.internal.view.SupportMenuInflater$MenuState.addItem(SupportMenuInflater.java:462)
    W/SupportMenuInflater( 1308): 	at android.support.v7.internal.view.SupportMenuInflater.parseMenu(SupportMenuInflater.java:196)
    W/SupportMenuInflater( 1308): 	at android.support.v7.internal.view.SupportMenuInflater.inflate(SupportMenuInflater.java:118)
    W/SupportMenuInflater( 1308): 	at com.grokkingandroid.sampleapp.samples.actionbar.actionviews.SearchViewFragment.onCreateOptionsMenu(SearchViewFragment.java:40)
    

    Whenever you migrate an existing project, I suggest you run a search over all sources – especially the resources. Search for “sherlock” to find out, if you’ve missed any references. Another good candidate for problems is be the manifest file if you previously used ActionBarSherlock styles directly within it.

    If you have corrected all menu files, you are done with the resources. Select Project -> Clean to clean the actionviews project and get rid of the android:textIsSelectable error marker. The Android Dev Tools generate a new R.java file and it’s time to have a look at the Java sources.

    Fixing fragments

    I’m going to show you first how to fix fragments and later on how to fix activities.

    Substituting SherlockDialogFragment with DialogFragment

    The first and most simple one to fix is the AboutFragment. You have to fix the inheritance since this class inherits from an ActionBarSherlock class which you want to migrate away from. Simply substitute SherlockDialogFragment with DialogFragment and the AboutFragment is fine. Of course you have to correct the imports by hitting Ctrl-O.

    Note: Eclipse asks you whether to use an import from stock Android or from the support library. Whenever eclipse offers you this alternative, you always have to use the imports of the support library:

    Select the support library versions whenever this choice is presented to you

    Select the support library versions whenever this choice is presented to you

    Substitute SherlockListFragment with ListFragment

    Next up is the SearchFragment. It inherits from SherlockListFragment. Replace this with the stock ListFragment and hit Ctrl-O.

    Replace getSherlockActivity() with getActivity()

    Two red markers remain – both for the method call to get an activity object. Simply replace getSherlockActivity() with getActivity() and the code is fine again.

    Substitute SherlockFragment with Fragment

    Now to those other fragments that make up the beef of the sample. Those fragments all inherit from the base class DemoBaseFragment. Again you have to change the type of the super class. Replace SherlockFragment with the stock Fragment class of the support library. Afterwards hit Ctrl-O and change the getSherlockActivity() calls to getActivity() calls as mentioned above.

    For the four remaining fragments change the imports first. ActionBarCompat needs no special Menu or MenuItem objects like ActionBarSherlock did. Thus two of the four fragments are immediately correct after fixing the imports. Those other two are a tiny bit more involved.

    Use MenuItemCompat for ActionViews and ActionProviders

    The problem is with ActionViews – the core content of the sample app. ActionBarCompat uses plain Menu objects. But those do not know of ActionViews prior to API level 11. So ActionBarCompat uses a helper class named MenuItemCompat to deal with ActionViews and ActionProviders.

    Instead of calling getActionView() on a MenuItem object you have to use MenuItemCompat.getActionView(). For example the new way to get hold of the ActionView in the SearchViewFragment looks like this:

    SearchView searchView = 
          (SearchView)MenuItemCompat.getActionView(item);
    

    The same applies to setting an ActionView. The PlaceholderActionViewFragment for example uses the following lines:

    MenuItemCompat.setActionView(
          PlaceholderActionViewFragment.this.mProgress, 
          R.layout.actionview_progress);
    

    For ActionProviders you would have to do the same – just with different method names of course.

    Fixing activities

    As with fragments you have to change the super classes for the activities as well. The actionviews project uses one base activity for all activities within the project. This class obviously is the starting point for changes to activities.

    Replace SherlockFragmentActivity with ActionBarActivity

    Changing the super class for activities is slightly different to the changes you applied to fragments in the previous steps. With fragments you simply change them to stock fragments of the support library. With activities on the other hand you have to use a super class of the ActionBarCompat library.

    Open BaseActivity and change the super class from SherlockFragmentActivity to ActionBarActivity.

    Replace getSupportMenuInflater() with getMenuInflater()

    One problem remains after fixing the imports. The first problem is the call to getSupportMenuInflater(). Simply replace it with getMenuInflater() instead.

    Replace Sherlock layout IDs

    The next activity you are going to fix is the ActionViewActivity. After fixing all imports there are still two red markers left. Those are for sherlock specific layout resources.

    First replace R.layout.sherlock_spinner_item with android.R.layout.simple_spinner_item. Next replace sherlock_spinnner_dropdown_item with R.layout.support_simple_spinner_dropdown_item. Edit: Thanks to George for his correction of my original recommendation (see his comment below).

    The respective lines should look like this after you applied those changes:

    ArrayAdapter<CharSequence> spinnerAdapter = 
          ArrayAdapter.createFromResource(
                getSupportActionBar().getThemedContext(), 
                resId, 
                android.R.layout.simple_spinner_item);
    spinnerAdapter.setDropDownViewResource(
          R.layout.support_simple_spinner_dropdown_item);
    

    For the two remaining activities, which I didn’t cover yet, you simply have to fix the imports to make them compile again. After that your project should contain no more errrors and should build fine.

    Lessons learned

    After reading this post you should be able to migrate an existing project which is based on ActionBarSherlock to ActionBarCompat. You have seen good reasons of why to do this and the steps to follow to get your project running again.

    There are other great posts about ActionBarCompat out there. Mark Allison wrote a series about ActionBarCompat and Antonio Leiva also has a three part series on ActionBarCompat. The last post also covers migrating from ActionBarSherlock. And Gabriele Mariotti also has multiple posts about ActionBarCompat. We all use different approaches – so look for the post style you like the most. If you feel important parts are missing here, have a look at these other posts.

    Till next time. Happy Coding – and Happy Migrating!

    ActionViews Sample App is on Bitbucket

    The sample app for my post about ActionViews is on Bitbucket. Besides Actionviews it serves also as the sample app for how to add ActionBarSherlock to projects, and for adding action items from within fragments.

    Here’s a screenshot of the demo:

    The demo app showing the SearchView in its collpased mode

    The demo app showing the SearchView in its collpased mode

    I plan on generating the scaffold for my demo apps so that I only have to add specific stuff and keep my work for the demos to a minimum. That on the other hand makes some parts of the code look a bit weird, others look pretty generic. You wouldn’t do it that way for a single purpose project.

    Since I like to blog about what is happening to me while developing apps, I use this post to tell you about three useful Android tools that I used while developing and preparing this app for release.

    The first two can be used to analyze the UI, the third is useful for spotting problems with stuff you might miss because you are too knowledgable of the way your app works.

    HierarchyViewer vs. UI Automator Viewer

    UI Automator Viewer is a tool that was released with Android pretty recently (sometime last year). According to the Android site it can be used to Analyze your Application’s UI. In fact it is a very nice tool to quickly get an overview of how the UI of an app is structured. UI Automator simply grabs the screen and shows you all views present. Here’s a screen of the Play Music app:

    UI Automator Viewer displaying the hierarchy of the Play Music app

    UI Automator Viewer displaying the hierarchy of the Play Music app

    On the left is the UI, on the right the hierarchy at the top and some properties of the currently selected element at the bottom. As you can see I have selected a tiny image at the bottom right corner of the album shot (whatever it is for).

    But the big downside of this tool is that it only shows what you can see. And if you wonder, why something is not visible, it can’t help you. Which I learned the hard way some days ago :-)

    I extracted parts of the container’s attributes to a common style. Then I applied this style to the other containers and deleted unnecessary attributes. And by doing so I deleted one attribute too many of a LinearLayout – the android:orientation attribute. A LinearLayout is horizontal by default and since I already had a TextView inside the container (the box header) any additional view wouldn’t be visible.

    Lint normally warns about that, but in my case I add the views in the code – and thus Lint couldn’t catch the problem. This silly mistake caused me to look in all directions, but not the right one. For way too long!

    Here’s what it looked like:

    The demo showing the container without the links

    The demo showing the container without the links

    In retrospect it’s obvious what went wrong and I wonder why I thought of other reasons at all, but well, one is always wiser in hindsight :-) I finally found the missing attribute using a plain old diff and having a closer look at what I actually had removed. But I could have spotted it earlier, had I known about UI Automator’s restriction to visible UI elements. There is a button “Toggle NAF Nodes” but that doesn’t help here either. This button is only useful to see elements which are visible but not reachable via navigational controls like a D-pad.

    Another Android tool, HierarchyViewer, could have saved me. This tool is so darn slow that I never really liked it. Which is why I had hoped (thought, actually) UI Automator Viewer would be enough.

    HierarchyViewer can be extremely useful, though. It really shows any view that is part of the hierarchy. Visible or not! So let me show you the hierarchy of my demo app, before I corrected my LinearLayout's orientation in both tools.

    In HierarchyViewer I immediately see that all my links had been added. But they were outside of the right edge of the screen. The bold red line is where my view is :-)

    Hierarchy Viewer showing my missing view

    Hierarchy Viewer showing my missing view

    Now the same view in the UI Automator Viewer (with the NAF toggle on):

    UI Automator viewer isn't showing all the views present in the LinearLayout

    UI Automator viewer isn’t showing all the views present in the LinearLayout

    So, don’t get me wrong: I know that UI Automator Viewer’s main task is to analyze your UI before writing uiautomator tests, but it would have been nice nonetheless if it could have been used for this as well. It’s a much nicer tool than Hierarchy Viewer.

    Monkey

    As a last step before releasing, I did a Monkey run. Monkey is a tool that simulates random clicks and interactions with the devices. No user would do it that way, obviously, but by doing so monkey uses combinations and clicks on places you never would do.

    By executing it’s random actions, Monkey helps you to find weak spots like Application Not Responding problems or unexpected crashes at odd places. Monkey uses the app in unexpected ways. Ways, of which we think, that no user in his right mind would choose them. But users do! Not because of their state of mind, but because the UI is not as intuitive as we thought. Or because they try to achieve goals that we didn’t think of.

    While Monkey runs, the screens of your app flash in quick succession and you see all kind of button presses and so on.

    As soon as a problem appears, Monkey stops and shows a modal dialog. One of the very rare cases where a modal dialog is okay. While monkey is running the devices isn’t usable anyway – and you want to see when something goes wrong.

    A warning though: Do not use Monkey for arbitrary apps on your device. As I’ve said, it does all kind of things – which means that your data is probably in a bad shape afterwards :-)

    With that said, it’s finally time for you to go over to the Bitbucket project page and grab the sources. Let me know any suggestions you have. Thanks!

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