With this recipe, we are going to complete the project we began in the previous recipe; we will implement an Android app that publishes the current device's position to RabbitMQ. This example is simpler than the previous one, as we are not going to plot the positions on a map, but we still need the Google Play services since we have decided to make use of their location service; it provides a useful abstraction for the available location sensors available on the device, letting the application be compatible with a wide spectrum of Android devices.
To put to work this recipe, we need:
API11
. Create a Blank Activity.commons-cli-1.1.jar
, commons-io-1.2.jar
, and rabbitmq-client.jar
) in the libs
directory of the project.Hello world!
TextView, created by the Eclipse wizard, insert a switch widget that we name followmeSwitch
. You can edit the corresponding XML layout file activity_main.xml
and insert the following:<Switch android:id="@+id/followmeSwitch" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="28dp" android:text="@string/followme" />
SenderService
class that extends IntentService
.MainActivity.java
:final Switch fms = (Switch)findViewById(R.id.followmeSwitch); fms.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButtonbuttonView, booleanisChecked) { if (isChecked) { serviceIntent = new Intent(MainActivity.this, SenderService.class); startService(serviceIntent); } else { stopService(serviceIntent); } } });
In this recipe, we have approached another typical pattern that we can meet by mixing RabbitMQ and Android technologies: publishing messages in the background, even when the user interface is not visible on the Android device.
We have first created a standard Android application with just a switch; on turning it on, we start delivering messages to the RabbitMQ broker. When turned off, we stop it.
So we have bound the actions of followmeSwitch
to the SenderService
(step 7). It's important to remember that when we start a background job with an Android service, the background events are still executed by the application's main thread, and we need to apply the same responsiveness guidelines that we follow when we design Android GUIs.
However, in our example, we have decided to make use of the IntentService
helper class that starts a background thread that can run indefinitely.
It's in this thread that we connect to the broker and periodically send RabbitMQ messages reporting the current position of the device acquired by calling locationClient.getLastLocation()
(see the source file with the class referred by the step 6).
As soon as the user turns off the switch, we just exit this thread.
By running this application on one device, and one of the previous recipes on another, we are able to communicate our georeferenced position by using RabbitMQ messages.
The Google localization client library allows raising events on location changes, so this should be the preferred method to send coordinates. This approach can be optimized to conserve battery usage on the device, but we have avoided it for the sake of simplicity.
However, the application is already fully functional; you can run many different devices as consumers—and all of them will update the position synchronously, as we publish the messages to a fanout exchange.
You can even run many producers concurrently, but the current implementation will just mix their data together; to draw many different traces from different devices, it comes handy to replace the fanout exchange with a topic exchange and give a different routing key to each producer.