Posted by & filed under Android.

In Parts 1 and 2 of this series we examined different methods of creating a reactive application on Android, where events (either UI events originating from the application user, or background events generated by the system) trigger certain actions. We examined using an event bus and Observables in the context of a demo application, a simple file downloader. In this post I will examine how you construct an Android application using an actor system.

Actor model of managing concurrency comes from Erlang. Akka provides Actor implementation in Java and Scala. I will omit detailed descriptions of actors and Akka, but if you would like an introduction to the topic I’ve listed some useful presentations below.

WARNING: The method described below is only for demonstration purposes, and should not be used in production. Akka framework has been optimized for use on server infrastructure, and is not a good fit on mobile for various reasons. That said, the actor model is in my opinion a good fit for structuring mobile applications, and assuming it gets support from a library it can be a significant improvement to the way we write mobile applications in the new world of multicore pocket-sized devices.

The code for the demo application is available on github. This application is written in Scala to make interaction with Akka less verbose, but if you are unfamiliar with the language don’t let that turn you away. Don’t focus too much on the syntax, just follow the concepts. If you want to try to build the application, the README file should provide the instructions to run it on your device or emulator.

All the code we need is packed into DownloadActivity.scala and Downloader.scala. There are a couple other files in the package that assist us. DownloadApplication.scala contains the custom application that initializes the actor system on start. AndroidDispatcher.scala is a custom Akka dispatcher that allows specified Actors to always run on the UI thread. The configuration for the akka system is in res/raw/akka, and describes the dispatchers. These are not optimal settings, only enough for the system to work.

Let’s now dig into DownloadActivity. As before, its just a container for the DownloadFragment. The only thing to notice is that the Activity extends TypedActivity, which is generated by the scala build tool plugin to create a scala-friendly development environment. The TypedActivity gives us easy access to typed views. When writing a Java Android app, you have to cast anything returned by Activity.findViewById from View to the type you want to work with (ImageView, Button, TextView, etc). But that information is available in the XML resources! So instead of losing it, the sbt plugin creates a mapping, and gives you the view of the correct type when you request it.

DownloadFragment houses all of our UI. The first method in the class may seem a bit cryptic if you haven’t worked with scala:

// Implicit conversion that lets us use anonymous functions as onClickListeners
implicit def onClickListener(f: (View => Unit)): View.OnClickListener = {
  new View.OnClickListener() {
    override def onClick(v: View) {
      f(v)
    }
  }
}

As the comment says, this sets up an implicit conversion allowing us to use lambda functions directly on buttons as click listener actions. The fact that it is implicit means the compiler will look for it whenever it needs a View.OnClickListener, but instead is given an anonymous function. The parameter to the method is a higher order function from View to Unit (scala’s equivalent of void, ie no return value). The method then returns a new instance of the View.OnClickListener with onClick method calling the function it was passed in. Jumping further down, it allows us to use simple functions in setOnClickListener calls:

rootView.findView(TR.downloadButton).setOnClickListener((v: View) => {
  downloadButtonActor.tell(ClickEvent(v.asInstanceOf[Button]), fragmentCompanion)
})
rootView.findView(TR.resetButton).setOnClickListener((v: View) => {
  resetButtonActor.tell(ClickEvent(v.asInstanceOf[Button]), fragmentCompanion)
})

We’ll come back to the actions attached to the buttons in a little bit.

Right at initialization DownloadFragment creates a few actors it will need:

val system = getApplication().asInstanceOf[DownloadApplication].actorSystem
val downloadButtonActor = system.actorOf(Props[DownloadButton]()
    .withDispatcher("akka.actor.main-thread"))
val resetButtonActor = system.actorOf(Props[ResetButton]
    .withDispatcher("akka.actor.main-thread"))
val fragmentCompanion = system.actorOf(Props(new DownloadFragmentActor())
    .withDispatcher("akka.actor.main-thread"))
val downloader = system.actorOf(Props(new Downloader()), "downloader")

system.actorOf gives an actor of type supplied in Props configuration. For some actors that do operations on the UI thread we also call Props.withDispatcher giving our custom dispatcher that pins the actor to the UI thread. Other actors (ex: the Downloader) should run on another thread, and not block the UI thread.

I also decided to create a Fragment companion actor to handle the events, defined as follows:

class DownloadFragmentActor extends Actor {
  def receive = {
    case event: DownloadProgressEvent => updateProgress(event)
    case DownloadFinishedEvent => {
      // Nothing that we need to do
    }
    case TriggerStartDownloadEvent => {
      downloader ! StartDownload(findView(TR.urlEditText).getText.toString)
    }
    case TriggerPauseDownloadEvent => downloader ! PauseEvent
    case TriggerResumeDownloadEvent => downloader ! ResumeEvent
    case TriggerResetDownloadEvent => {
      updateProgress(DownloadProgressEvent(0, 0))
      downloadButtonActor ! ResetButtonState(findView(TR.downloadButton))
      downloader ! ResetEvent
    }
  }
  
  def updateProgress(progress: DownloadProgressEvent) {
    // View elements are wrapped in an Option, so foreach will
    // apply only to ones that are not None/null.
    progressBar foreach (_.setProgress(progress.getProgress))
    downloadProgressTextView foreach (_.setText(String.format("%s / %s",
      progress.getLoadedBytes, progress.getTotalBytes)))
  }
}

Actors define the receive function which gets called when a message arrives. In it we match the message type using scala’s pattern matching – switch statement on steroids. Thanks to this ability we can define the messages by case classes or case objects (in this case, singleton instantiations where a case class would be without parameters). I won’t go into the details of specific message handling just yet, let’s look through the rest of the application:

class DownloadButton extends Actor with ActorLogging {
  def receive = download

  val download: Receive = {
    case ClickEvent(v: Button) => {
      sender ! TriggerStartDownloadEvent
      v.setText("Pause")
      context.become(pause)
    }
    case RestoreButtonState(v: Button) => v.setText("Download")
    case ResetButtonState(v: Button) => performReset(v)
  }

  val pause: Receive = {
    case ClickEvent(v: Button) => {
      sender ! TriggerPauseDownloadEvent
      v.setText("Resume")
      context.become(resume)
    }
    case RestoreButtonState(v: Button) => v.setText("Pause")
    case ResetButtonState(v: Button) => performReset(v)
  }

  val resume: Receive = {
    case ClickEvent(v: Button) => {
      sender ! TriggerResumeDownloadEvent
      v.setText("Pause")
      context.become(pause)
    }
    case RestoreButtonState(v: Button) => v.setText("Resume")
    case ResetButtonState(v: Button) => performReset(v)
  }

  def performReset(v: Button) {
    v.setText("Download")
    context.become(download)
  }
}

DownloadButton is an actor companion for the UI button view. It captures the button state by using context.become() and handling the restore events (by setting appropriate text upon rotation).

The download logic has been created into an actor in Downloader.scala. (Side note, Scala doesn’t have the same restrictions as Java with regards to placement of classes in files, so multiple classes are frequently found in one file. This sometimes makes them hard to find, so make sure not to abuse this feature). The Downloader actor has two states – awaiting download, and downloading. When awaiting download, it accepts a start download message that places it into the downloading state. In it, a Future is kicked off to perform the download on a separate thread, while still accepting messages to control the process (pause, resume, reset). As before the download here represents a process you would like to happen in the background detached from your application UI, since you never block the UI thread.

Let’s now trace through a usecase and see the message flow in the actor system that’s created.

When you click on the Download button, a ClickEvent is sent to the DownloadButton actor. Since we’re coming from outside the akka system we provide the sender of the message to be the DownloadFragmentActor companion:
downloadButtonActor.tell(ClickEvent(v.asInstanceOf[Button]), fragmentCompanion)

(Side note, infix operator (dot) is optional in Scala, and exclamation point is a synonym for the tell method, so above can be written as downloadButtonActor ! (ClickEvent(v.asInstanceOf[Button]), fragmentCompanion)).

Next, the event is handled in the download method on the DownloadButton. That generates a TriggerStartDownloadEvent that gets sent to the sender, which we defined to be the DownloadFragmentActor. There a StartDownload message gets sent to the downloader, with the URL extracted from the EditText view. In the downloader, the download is triggered, and the Actor switches into the awaitingDownload functionality to properly handle pause/resume/reset events. I invite you to do the same exercise with other messages to see how they propagate through the hierarchy.

I hope with this brief introduction you can see advantages to using an actor model for designing your application. To summarize the actor system use on Android:

  • Abstractions over state and concurrency handling, pushing the details into the framework and out of your code.
  • Limited support at this time in the Android ecosystem.

This post concludes the series, but the topic is certainly far from complete. Are there any methods you like to use to create Android applications in a reactive fashion? If so, please share!

Resources:

Posted by & filed under Android.

In this section we will attempt to produce the same application as in Part 1, but using RxJava. If you’re not familiar with RxJava, I highly recommend watching a Netflix presentation on the topic. I’ll assume you’re familiar with the basics of the library.

As a reminder, we’re exploring different ways of communicating between threads in a way to account for application state changes. The source code of the demo app is available on github, so feel free to load it into Android Studio and play around with it.

Outside the core RxJava there is a library specifically for Android that allows to specify a thread to use for observation of events. This makes it easier to generate events on a background thread, but act upon them on a UI thread. We declare it as a dependency in the Gradle build script:

compile group: 'com.netflix.rxjava', name: 'rxjava-android', version: '0.15.1'

The rest of the application is very similar to what was developed in Part 1. Let’s go through the key differences.

When we create the view in DownloadFragment, we create a clickObservable:

// Create an observable, and set up OnClickListeners to post to it
Observable<ClickEvent> clickObservable = Observable.create(
     new Observable.OnSubscribeFunc<ClickEvent>() {
           @Override
           public Subscription onSubscribe(final Observer<? super ClickEvent> observer) {
                handleReset = new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          observer.onNext(new ResetEvent(v));
                      }
                };
                handleDownload = new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          observer.onNext(new DownloadStartEvent(v));
                      }
                };
                handlePause = new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          observer.onNext(new DownloadPauseEvent(v));
                      }
                };
                handleResume = new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          observer.onNext(new DownloadResumeEvent(v));
                      }
                };

                Button resetButton = ((Button) rootView.findViewById(R.id.resetButton));
                resetButton.setOnClickListener(handleReset);
                Button downloadButton = ((Button) rootView.findViewById(R.id.downloadButton));
                downloadButton.setOnClickListener(handleDownload);

                /**
                 * Restore state of the views based on the fragment instance state
                 * If not done, the center button stays in "download" state that
                 * the view is initialized with
                 */
                if (downloadThread != null) {
                       if (downloadThread.isRunning() && !downloadThread.isKilled()) {
                             switchToPause(downloadButton);
                       } else if (!downloadThread.isRunning() && !downloadThread.isKilled()) {
                             switchToResume(downloadButton);
                       }
                }

                return Subscriptions.empty();
          }
     });

In this block we define the OnClickListeners that post events to the observable upon a click on the button. As in Part 1, you wouldn’t normally do this, but I’m taking the example to an extreme to see how it would look if the main mode of communication were event driven. To post the click event we call the onNext method on the observer.

There is some logic to restore the state. If a device gets rotated, the DownloadFragment instance is retained (because we called setRetainInstance(true)), but the activity holding the fragment is recreated. After the fragment is reattached to the new activity, its view is recreated. This can happen in the process of download going on, so the views need to be returned to the state they’re expected to be in.

One other thing to notice is that the clickObservable is of type Observable<ClickEvent>. Therefore all events we can post to it need to either be ClickEvent, or subclass it. In order to subscribe to this stream we have to explicitly declare that we accept events of type ClickEvent. This provides some compile-time safety, but at the same time makes it tougher for one subscriber to accept different types of events.

Next we create a subscription from the clickObservable we just created:

clickSubscription = AndroidObservable.fromFragment(this, clickObservable)
      .subscribeOn(AndroidSchedulers.mainThread())
      .subscribe(this);

The DownloadFragment gets subscribed to the clickObservable, but before it does we subscribe on the Android UI thread using AndroidSchedulers.mainThread(). This makes it safe for us to modify UI views. The reason we can subscribe DownloadFragment, is that it implements Observer interface with the following methods:

@Override
public void onCompleted() {
    // ignore
}

@Override
public void onError(Throwable throwable) {
    Log.e(DownloadActivity.class.toString(), "Got an error from the Observable", throwable);
}

@Override
public void onNext(ClickEvent clickEvent) {
    if (clickEvent instanceof ResetEvent) {
        answerReset((ResetEvent) clickEvent);
    }
    if (clickEvent instanceof DownloadResumeEvent) {
        answerDownloadResume((DownloadResumeEvent) clickEvent);
    }
    if (clickEvent instanceof DownloadPauseEvent) {
        answerDownloadPause((DownloadPauseEvent) clickEvent);
    }
    if (clickEvent instanceof DownloadStartEvent) {
        answerDownloadStart((DownloadStartEvent) clickEvent);
    }
}

onCompleted can be ignored in this case because we set up an infinite stream. onError simply logs the error that is received, because we’re not expecting any. onNext is where we process the received event by matching it against expected classes. Based on the type of the event object we receive, we call the appropriate method. For example, here is how we handle download start request:

public void answerDownloadStart(DownloadStartEvent event) {
    downloadThread = new Downloader(urlEditText.getText().toString());
    downloadThread.start();

    // Subscribe to the progress observable
    // Sample the stream every 30 milliseconds (ignore events in between)
    // Upon receiving an event, update the views
    downloadThread.getProgressObservable()
           .sample(30, java.util.concurrent.TimeUnit.MILLISECONDS)
           .observeOn(AndroidSchedulers.mainThread())
           .subscribe(new Action1<DownloadProgressEvent>() {
                @Override
                public void call(DownloadProgressEvent event) {
                    progressBar.setProgress((int) event.getProgress());
                    downloadProgress.setText(String.format("%s / %s",
                          event.getLoadedBytes(), event.getTotalBytes()));
                }
            });
    switchToPause(((Button) event.getView()));
}

Here we create a new Downloader thread, and start it. We then get a progress observable from it. The observable is a stream of DownloadProgressEvents. We have to observe the stream on the UI thread because we want to modify the views to notify the user of the download progress, but we don’t want to do too much work on the main thread, so the first modification we run to the stream is to sample it every 30 milliseconds. Sample, just one of the many operations one can call on an observable, processes one event per specified time period, and ignores all others that might have come in. We then observe the sampled stream on the Android main UI thread, and subscribe an anonymous inner class to update progress views upon receiving an event.

How do we get this progress observable in the first place? Let’s look in the Downloader:

public Downloader(String url) {
   this.url = url;
   // Seed the event stream with the first event.
   progressSubject = BehaviorSubject.create(new DownloadProgressEvent(0, 0));
}

Right in the constructor we create a BehaviorSubject. Its one of the Subjects provided by RxJava. In this case at the point that we subscribe to it, we get the latest event.

The rest of the code of the Downloader is exactly the same as in the first part, except for reporting progress:

private void reportProgress() {
    progressSubject.onNext(new DownloadProgressEvent(loadedSize, totalSize));
}

We simply call onNext on the BehaviorSubject with the DownloadProgressEvent.

One thing you may notice in testing the application is that Reset doesn’t clear the progress views. Actually, it does, but because the communication is asynchronous, additional progress events may come in after the download has been reset.

To summarize:

  • RxJava is excellent for streaming events.
  • The library is well supported on Android with Android specific bindings.

RxJava is best used for cases where you have streams from the application – results coming from the network, sensor streams, motion events, and so on. Two way communication is not easy to set up with RxJava. But there is a framework for asynchronous message passing that may make it easier. I will cover it in the next installment of this series.

Posted by & filed under Android.

From what I’ve seen, vast majority of bugs and crashes programmers face on Android are around state and concurrency. These issues cause serious headaches not only in mobile applications, but they have a special flavor in Android. Specifically, all long running operations (network calls, file access, etc) must be done off the main (UI) thread. Once taken off the main thread, one needs to set up communication between UI and background threads to signal operation progress and communicate results. This is further complicated by device state changes of the application outside the programmer control. As an example, a rotation triggers a rebuild of the Activity, so if there were a thread running in the background, its launcher UI may no longer be there. Incorrect handling can be a cause of memory leaks or crashes.

Recent additions to Android, for example Fragments and Loaders, attempt to resolve some of these issues, but either fall short or bring their own problems. Just as an example, my original plan for this demo app was to use a Loader, but because I wanted to keep track of the download progress I had to fall back to using traditional threads.

This blog series will attempt to demonstrate some alternative ways of setting up asynchronous communication between Android components. The example application is a simple download helper. It accepts the URL of the file to download, and shows a progress bar. Download can be paused, resumed, or reset (to demonstrate two way communication). Complete source code can be found on github. Feel free to clone it, and run in Android Studio.

OttoDownloader Screenshot

To be clear, this is not a tutorial on how to create a download application! If that’s your task, I would look at Services with an AsyncTask for the actual download (reminder: Service, although running in the background, still runs in the UI thread, that you never block!) Instead I’ll concentrate on the message passing aspect of an Android application.

In the first part I will use a message bus to handle all communication. For that we’ll make use of a Square library Otto. To be fair, the example takes it to an extreme in order to push all communication to be event driven and as asynchronous as possible, including handling touch events on the button. Otto bus really excels at communication between different view components, where an alternative would be either view traversal (tedious, and tough to evolve), or callback interface implementation (safe, but verbose). One example is communicating between different fragments, where an action in one should trigger a change in another. For this application Otto is not the best fit (its actually synchronous), but still a good introduction to the concept of an event driven application.

Let’s walk through the demo application:

DownloadApplication: Subclasses standard Android application class, and provides access to a global Otto bus.

DownloadActivity: Contains both the main Activity and the Fragment. The Activity is used only as a container for the Fragment, majority of the work is handled by the Fragment.

Downloader: Subclasses a Java Thread, implementing the run() method to perform the file download.

There are also a few classes in the events package, but they’re relatively straightforward.

Let’s start with the Downloader – it takes a URL to download, and a callback interface.

public Downloader(String url, DownloadProgressReport reportCallback) {
    this.url = url;
    callback = reportCallback;
}

It would be nice to generate events directly from here, but doing so fails with an Otto exception due to attempts to access a bus pinned to the Android main thread (see more details below). The actual code to perform download is very standard for Java – we create a bogus file in /sdcard, and copy bytes from the InputStream into the FileOutputStream.

URL toDownload = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) toDownload.openConnection();

urlConnection.setRequestMethod("GET");
urlConnection.connect();

// We don't care about the downloaded file, just store it anywhere
File sdCardRoot = Environment.getExternalStorageDirectory();
File outFile = new File(sdCardRoot, "outfile");
FileOutputStream fileOutput = new FileOutputStream(outFile);

InputStream inputStream = urlConnection.getInputStream();
totalSize = urlConnection.getContentLength();
loadedSize = 0;

byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
while (!killed && (bufferLength = inputStream.read(buffer)) > 0) {
       while(!running && !killed) {
            Thread.sleep(500);
       }
       if (!killed) {
            fileOutput.write(buffer, 0, bufferLength);
            loadedSize += bufferLength;
            reportProgress();
       }
}

On each iteration we call a progress callback with the number of bytes we have downloaded and total bytes for the file.

private void reportProgress() {
    callback.reportProgress(loadedSize, totalSize);
}

DownloaderFragment takes care of the view. In the onCreate method it registers itself to the Bus.

@Override
public void onCreate(Bundle savedInstanceState) {
     getEventBus().register(this);
     super.onCreate(savedInstanceState);
}

Methods annotated with @Subscribe annotation then receive the corresponding events. All buttons are configured to post events to the bus upon a click – center button changes behavior depending on the download state, and the OnClickListener gets swapped out accordingly.

@Subscribe
public void answerDownloadPause(DownloadPauseEvent event) {
     downloadThread.pause(true);
     switchToResume(((Button) event.getView()));
}

private void switchToResume(Button downloadButton) {
     downloadButton.setText(getString(R.string.resume));
     downloadButton.setOnClickListener(handleResume);
}

The answerDownloadStart kicks off the download by instantiating a new download thread and starting it. Besides the URL, it provides a callback class that posts appropriate events to the Bus from the thread.

@Subscribe
public void answerDownloadStart(DownloadStartEvent event) {
      downloadThread = new Downloader(
          urlEditText.getText().toString(),
          new Downloader.DownloadProgressReport() {
          
          @Override
          public void reportProgress(final long loaded, final long total) {
               final Activity activity = getActivity();
               if (activity != null) {
                   activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ((DownloadApplication) activity.getApplication()).getBus()
                                    .post(new DownloadProgressEvent(loaded, total));
                        }
                    });
                }
          }

          @Override
          public void reset() {
               final Activity activity = getActivity();
               if (activity != null) {
                   activity.runOnUiThread(new Runnable() {
                       @Override
                       public void run() {
                            switchToDownload(((Button) getView().findViewById(R.id.downloadButton)));
                       }
                   });
               }
          }
      });
      downloadThread.start();
      switchToPause(((Button) event.getView()));
}

Note: It is possible to initialize the bus with new Bus(ThreadEnforcer.ANY). This would allow events to be posted from any thread. But they would be consumed on the same thread, so any attempts to update the views would result in a runtime exception (they can only be modified by the UI thread). Hence, the default way to instantiate an Otto bus is the safest.

We also take precaution to check the activity not to be null prior to posting Runnables to run on UI thread. If a device is rotated, the original Activity is no longer there – in fact, there may be a period when the Fragment is in a detached state, and the attempt to call its Activity would fail with a NullPointerException.

If you run the app on your device, you may hit some performance issues – the interface may lag. Otto bus doesn’t allow dropping of events, and every one is processed. In addition, garbage collection is triggered often, as every progress report is a new object. Finally, all the view updates all taking place on the UI thread. We will see some ways to control the message flow in the next installment.

To summarize:

  • Otto library lacks ability to control message flow.
  • Thread enforcement is left up to the programmer.
  • Works best for communication between Fragments or other views

In the next installment we’ll take a look at RxJava, and how it can be used to drive the same app.

 

 

Posted by & filed under Programming.

Let’s say you want to make a static list view, perhaps because all the items in the list fit on the screen (no matter how small). Android doesn’t offer an easy way to accomplish this with something like myListView.setEnableScrolling(false); There is a StackOverflow question that provides an easy way to do it using a custom view, as well as a few other options that work by preventing the move motion event from reaching the ListView. That works well, but if you touch one of the items in the list, and move your finger away from the view, the event bound to that item view still fires. The behavior the user usually expects is to cancel the event in this case – think of touching a button, and changing your mind mid-press. That can be done using a slightly more complex dispatchTouchEvent method. The complete class is below:

 

Now replace your ListView in the layout by the custom implementation, and you have a properly functioning static ListView.

 

Posted by & filed under Programming.

Update 10/31/2013: The WebViewChromium is now implemented in Android 4.4 KitKat!

If you’ve ever used WebView in Android, you know that its a double edged sword. On the one hand being able to bring the full power of HTML and Javascript into a section of your application frees you up from vastly more complicated native coding that you would have to do to replicate something that can easily be done with standard web technologies. On the other hand, WebView typically uses the standard browser implementation on the device you’re using, which is typically tied to manufacturer’s updates, and therefore lags modern browsers, like Chrome, by a significant margin in terms of HTML5 feature support. Debugging rendering issues in a WebView is also painful to say the least.

To combat this problem, Google has promised “Chromium” implementation for the WebView – essentially using the Chrome rendering engine to power WebView. This was first talked about at Google IO 2012. Android 4.3 shipped yesterday, and WebViewFactory shows experimental support for Chromium. However, the crucial webviewchromium.jar is still missing from the /system/framework directory to enable this support.

So for now, we’re still left where we were. One can only hope for the next release to finally have this working out of the box.