Showing posts with label Intent. Show all posts
Showing posts with label Intent. Show all posts

Nov 20, 2014

Introducing Android Network Intents

Android Network Intents is a library that I wrote for Lands of Ruin - a game that two friends and I are developing. To avoid a complicated network setup to play the game against a friend, we needed a way to discover games running on the local network. Android offers a Network Service Discovery (NSD) since API level 16 (Android 4.1) but we kept running into problems using it. This lead to writing this library.

What does the library do?
The library allows you to send Intents to listening clients on the local network (WiFi) without knowing who these clients are. Sender and receiver do not need to connect to each other. Therefore the library can be used to write custom discovery protocols.

Sending Intents (Transmitter)
An Intent is sent by using the Transmitter class. A TransmitterException is thrown in case of error.

Sending an Intent

Receiving Intents (Receiver)
Intents are received using the Discovery class. Once started by calling enable() the Discovery class will spawn a background thread that will wait for incoming Intent objects. A DiscoveryListener instance will be notified about every incoming Intent.

Writing a DiscoveryListener to receive events.

Starting and stoping the discovery.

Things you should know
The Intents are sent as UDP multicast packets. Unlike TCP the UDP protocol does not guarantee that a sent packet will be received and there is no confirmation or retry mechanism. Even though losing a packet only happens rarely in a stable WiFi, the library is not intended for using as a stable communication protocol. Instead you can use it to find other clients (by sending an Intent in a periodic interval) and then establish a stable TCP connection for communication.

On GitHub you can find a chat sample application using the library. While this is a convenient example, it is not a good use of the library for the reasons state above. You obviously do not want to lose chat messages.

We are using the library for almost two years in Lands of Ruin and didn't observe any problems. However the game only runs on tablets so far. In theory the library should run on all Android versions back to API level 3 (Android 1.5) but this has obviously never been tested.

You can find Android Network Intents on GitHub.

Aug 22, 2013

Read the code: IntentService

In the new category Read the code I’m going to show the internals of the Android framework. Reading the code of the framework can give you a good impression about what’s going on under the hood. In addition to that knowing how the framework developers solved common problems can help you to find the best solutions when facing problems in your own app code.

What is the IntentService class good for?
This article is about the IntentService class of Android. Extending the IntentService class is the best solution for implementing a background service that is going to process something in a queue-like fashion. You can pass data via Intents to the IntentService and it will take care of queuing and processing the Intents on a worker thread one at a time. When writing your IntentService implementation you are required to override the onHandleIntent() method to process the data of the supplied Intents.

Let’s take a look at a simple example: This DownloadService class receives Uris to download data from. It will download only one thing at a time with the other requests waiting in a queue.

DownloadService


The components
Before we dip into the source code of the IntentService class, let's first take a look at the different components that we need to know in order to understand the source code.

Handler (documentation) (source code)
You may already have used Handler objects. When a Handler is created on the UI thread, messages can be posted to it and these messages will be processed on the UI thread.

ServiceHandler (source code)
The ServiceHandler inner-class is a helper class extending the Handler class to delegate the Intent wrapped inside a Message object to the IntentService for processing.

ServiceHandler inner class of android.app.IntentService

Looper (documentation) (source code)
The Looper class has a MessageQueue object attached to it and blocks the current thread until a Message is received. This message will be passed to the assigned Handler. After that the Looper processes the next message in the queue or blocks again until a message is received.

HandlerThread (documentation) (source code)
A HandlerThread is a Thread implementation that does all the Looper setup for you. By creating and starting a HandlerThread instance you will have a running thread with a Looper attached to it waiting for messages to process.

Read the code!

Now we know enough about all the components to understand the IntentService code.

onCreate()

IntentService.onCreate()

At first a HandlerThread is created and started. We now have a background thread running that already has a Looper assigned. This Looper is waiting on the background thread for messages to process.

Next a ServiceHandler is created for this Looper. The Handler’s handleMessage() method will be called for every message received by the Looper. The ServiceHandler obtains the Intent object from the Message and passes it to the onHandleIntent() method of the IntentService.

onStart()

IntentService.onStart()

The onStart() method is called every time startService() is called. We wrap the Intent in a Message object and post it to the Handler. The Handler will enqueue it in the message queue of the Looper. The onStart() method is deprecated since API level 5 (Android 2.0). Instead onStartCommand() should be implemented.

onStartCommand()

IntentService.onStartCommand()
In onStartCommand() we call onStart() to enqueue the Intent. We return START_REDELIVER_INTENT or START_NOT_STICK depending on what the child class has set via setIntentRedelivery(). Depending on this setting an Intent will be redelivered to the service if the process dies before onHandleIntent() returns or the Intent will die as well.

onDestroy()

IntentService.onDestroy()
In onDestroy() we just need to stop the Looper.

Conclusion

The IntentService code is quite short and simple, yet a powerful pattern. With the Handler, Looper and Thread class you can easily build your own simple processing queues.

Oh, and if you are looking for an exercise. The code of the onCreate() method contains a TODO comment that I omitted above:

TODO in onCreate()

May 27, 2013

Sharing the taken picture - Instant Mustache #9

This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection. Click here to get a chronological list of all published articles about Instant Mustache.

Up to now our app can take and view pictures. The next step is to share the taken picture with other Android apps. This is done via Intents. The Intent system is one of the most powerful features of Android. It allows us to interact with any app that accepts images with almost no extra afford.

We could create an ActionBar item and when clicked launch an Intent to share the image but instead we are going to use a ShareActionProvider. The ShareActionProvider adds a share icon to the ActionBar as well as the icon of the app that the user has shared pictures the most with. By clicking this icon the user can share directly with this app. In addition to that the ShareActionProvider shows a sub menu with more apps that the given picture can be shared with.

A ShareActionProvider with Google+ as default share action.

Sub menu of a ShareActionProvider.

If sharing is a key feature of your activity, you should consider using the ShareActionProvider.

We start by creating an XML menu file for adding the share action. For legacy reasons the ActionBar uses the same approach for creating action items as the menu in Android 2.x.

activity_photo.xml

Once we inflated the menu in onCreateOptionsMenu() we need to set the Intent used to share the photo.

PhotoActivity.initializeShareAction()

Let's take a look at the different components of the Intent:
  • ACTION_SEND: The default action used for “sending” data to an other unspecified activity.
  • MIME type: The MIME type of the data being sent. Other apps can define multiple MIME types they accept. We are sending a JPEG image and therefore we are using the MIME type “image/jpeg”. To learn more about MIME types start with the "Internet media type" Wikipedia article.
  • EXTRA_STREAM: Uri that points to the data that should be sent. In our case the Uri is pointing to the image file on the external storage.

That's it already. For all changes done to the code base, see the repository on GitHub. In the next article we'll polish some aspects of the app before we start implementing the Face detection feature.

Oct 30, 2012

Displaying the taken picture – Instant Mustache #7

This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection. Click here to get a chronological list of all published articles about Instant Mustache.

Writing the PhotoActivity

In the last article we wrote the code to take a camera picture and save it on the external storage. After saving the file the activity will be finished and a Toast will show up. This is not really user-friendly so now we'll write our next activity which will display the taken picture and later offer the option to share this picture.

We'll start by creating an empty activity called PhotoActivity and add it to the manifest of our application. For now the layout will only contain an ImageView to display the picture:

activity_photo.xml

Instead of showing a toast in our CameraActivity we create an Intent to start the PhotoActivity and use setData(Uri) on the Intent object to pass a Uri pointing to the picture file:

onPictureTaken() - CameraActivity.java

In onCreate(Bundle) of the PhotoActivity we'll retrieve the Uri from the Intent and pass it to the ImageView. The ImageView will take care of loading the picture from the external storage and displaying it.

onCreate() - PhotoActivity.java

And that's already all the code we need for the first version of the PhotoActivity.


CameraActivity (left) and PhotoActivity (right)