Android is one of the fastest growing operating systems and software stacks for smartphones. OS smartphones ranked second among all smartphone OS handsets sold in the U.S. in the first quarter of 2010. Dell, HTC, Motorola and Samsung are some of the manufacturers using this operating system.
Google opened the source code under an Apache License and now the Android SDK allows developers to write managed code in the Java language, controlling the device via Google-developed Java libraries. The SDK includes a comprehensive set of development tools, such as a debugger, libraries, a handset emulator, documentation, sample code and tutorials.
Applications that run in the background are supported in Android in contrast to iPhone. All of these facts stimulate me to research this interesting technology. I decided to make an application running in the background and receiving the GPS location. The main goal was to inform the user not to write or read text messages while he or she is driving.
It is pretty easy to develop an Android application, especially if you are using Eclipse. You can download the latest version of the Android SDK from the official site. There are a lot of tutorials explaining how to install and use the SDK in Eclipse, if you are a beginner you can take a look at the developer’s guide.
Utilizing the GPS Module
As you may know smartphones have a gps module which provides the current location. This feature is used in many applications. To implement it you have to modify the AndroidManifest.xml, this is the main configuration file.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
With these permissions you tell to the application that the GPS module will be used and the application is given access to it.
The Activity Class
There is one very important class in an application’s overall lifecycle – the Activity class. It takes care of creating a window for you in which you can place your UI. But this activity is not enough to create a background process. It should be used in conjunction with another object from the ContextWrapper to achieve the behavior of an application component that runs in the background and doesn’t interact with the user. This functionality is given up by the Service class. Both the activity and the service should be declared in the android manifest file.
My idea is to create a main activity class and in the onCreate() method call the service. But when something is started, there needs to be a way to stop it. The best place to stop the service is in the onDestroy() method of the main activity. These two methods are overridden because the main activity has to extend the Activity.java class. They look like:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
// setup and start MainService
MainService.setMainActivity(this);
Intent svc = new Intent(this, MainService.class);
startService(svc);
} catch (Exception e) {
Log.e(">>>", "Problem creating the UI", e);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// stop MainService
Intent svc = new Intent(this, MainService.class);
stopService(svc);
}
This is how the activity class looks. The service class will manipulate the GPS module data. It will get the location in a time interval, get the speed or calculate it if it is not available and finally if the speed is more than 10km/h it will inform the user not to use the phone’s features while driving in order to avoid accidents.
The Service Class
As the main activity extends Activity.java class, the service should extend the Service.java class. The service is started in the overridden method onCreate() of the class.
// service business logic
private void startService() {
TimerTask timerTask = new TimerTask(){
public void run() {
getUpdateLocation();
}
};
timer.scheduleAtFixedRate(timerTask,0,UPDATE_TIME_INTERVAL);
Log.i(getClass().getSimpleName(), "Timer started!");
}
First a timer object is needed which will take care of calling the service. To schedule the timer you have to prepare a TimerTask instance, which calls your business logic. In the example it is called the getUpdateLocation() method, its functionality will be explained later in this post. The timer is scheduled with the timer task and the specified time interval passed as a constant.
Lets take a look at the getUpdateLocation() method. As the title says, the method gets the location from the LocationManager.java class. The locations are separated by providers, so they are filtered with a criteria. Some GPS providers send the speed of the device. But if the speed is not received, it can easily be calculated as a quotient of the distance between the current and previous location with the subtraction of the two times.
private void getUpdateLocation() {
Log.i(getClass().getSimpleName(), "background task - start");
// get the system location service
locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
// create criteria to filter the providers
Criteria criteria = new Criteria();
bestProvider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(bestProvider);
date = new Date();
if(currentLocation == null){
currentLocation = locationManager.getLastKnownLocation(bestProvider);
currentDate = new Date();
}
float speed = calculateSpeed(location);
// speed > (10km/h = 2.78m/s)
if(speed > SPEED_LEVEL){
Looper.prepare();
Context context = getApplicationContext();
CharSequence text = MESSAGE;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
Looper.loop();
}
// set the currentLocation and currentDate with new values
// for the next iteration
currentLocation = location;
currentDate = date;
Log.i(getClass().getSimpleName(), "background task - end");
}
The user will be informed with a warning message, if the calculated speed is more than a specified value. This is the business logic, but there is one other thing to take care of – the timer. The timer is started in the onCreate() method of the service class. It will be stopped in the onDestroy() method of the service class. The cancel() method will then be called in order to cancel the timer and remove any scheduled tasks.
if (timer != null) {
timer.cancel();
}
The completed application will run in the background and inform the user with a message that his or her speed is more than 2.78 meters per second.
Facebook Application Response Timeout
Have you ever gotten the message The URL [your application url here] did not respond. even when everything seems to be working on your side?
One probable reason is that Facebook has a certain response timeout – approximately 12 seconds. If your page fails to respond in this time, Facebook will leave it and display an error message. I used a few simple tricks and managed to work around this issue. Try them out:
Make the Facebook application lighter:
Speed up your Facebook app:
AJAX calls have the same timeout issue (although the timeout here is approximately 13 seconds). Additionally all AJAX calls pass through the Facebook server which slows them down. The result is the following JavaScript error: “error”:1349011,”errorSummary”:”Failed to fetch app Ajax” .
I found a simple solution to avoid it: Use FBJS AJAX and a timer to abort the request when it reaches the time limit and send a new one.
Facebook API Response Time and Error Count
The Facebook API itself sometimes has latency issues causing your app pages to be fetched slower, increasing the risk of reaching the response timeout. Errors in request to their servers are also known to happen. You should always be informed about the Facebook Platform Status.
Syntax Limitations in FQL
The Facebook API allows you to make your own queries using a query language similar to SQL. There is a list of tables you can access (you can only view information; you are not allowed to update the information in any of these tables). You can easily make your own queries, but you should keep in mind that you cannot do a number of normal (for SQL) things such as join tables, use ‘distinct’, ‘limit’, ‘group by’, etc., or use “from” against more than one table. You can easily do these operations in the code, however. Combined with the use of the multiquery functionality, things should work almost as fast as if you were using pure SQL.
Facebook API Changes
As you may guess, the Facebook API still is in development, so you should keep yourself up to date with the constant changes in its platform. Some of these changes are potentially breaking, some features are being deprecated or changed, and some cool new things are being added. It is useful to read the Facebook Developer Roadmap to be informed for the specific changes that have been planned and when to expect them. Here are some of the upcoming ones:
Until recently, some of the API changes, even when prepared for them, had unexpected effects on some applications (in some cases, bugs appeared) and there was nothing we could do about it.
In late February, Facebook introduced a tool to help us prepare for the changes – the Migrations tool. When Facebook announces a new feature or fix, you can first do some testing before going to the Migrations tab in your application settings and choosing to enable it (it is disabled by default).
In conclusion, I can assure you that whatever problems you may stumble upon there is a huge community of developers willing to help you out. Just go to the Facebook Developers Forum. There is also lots of documentation and useful tips in the Facebook Developers Wiki. Have fun!