Creating a Service Android

Creating an Android service involves extending the Service class and adding a service block to the AndroidManifest.xml permissions file. The GPXService class overrides the onCreate(), onStart(), onStartCommand(), and onDestroy() methods to begin with.Defining the service name enables other applications to start the service that runs in theackground and stop it. Both the onStart() and onStartCommand() methods areessentially the same, with the exception that onStart() is deprecated in API Levels 5 and above. (The default implementation of the onStartCommand() on API Level 5 or greater is to call onStart() and returns an appropriate value such that behavior will be compatible to previous versions.) In the following example, both methods are implemented.

For this example, we implement a simple service that listens for GPS changes, displays notifications at regular intervals, and then provides access to the most recent location data via a remote interface. The following code gives a simple definition to the Service class called GPXService:

public class GPXService extends Service {
public static final String GPX_SERVICE =
“com.androidbook.GPXService.SERVICE”;
private LocationManager location = null;
private NotificationManager notifier = null;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
} @Override
public void onStartCommand(Intent intent, int flags, int startId) {
super.onStart(intent, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}

You need to understand the lifecycle of a service because it’s different from that of an activity. If a service is started by the system with a call to the Context .Start Service() method, the onCreate() method is called just before the onStart() or onStartCommand() methods. However, if the service is bound to with a call to the Context.bindService() method, the onCreate() method is called just before the onBind() method. The onStart() or onStartCommand() methods are not called in this case. We talk more about binding to a service later in this chapter. Finally, when the service is finished—that is, it is stopped and no other process is bound to it—the on Destroy() method is called. Everything for the service must be cleaned up in this method.

With this in mind, here is the full implementation of the onCreate() method for the GPXService class previously introduced:

public void onCreate() {
super.onCreate();
location = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
notifier = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
}

Because the object doesn’t yet know if the next call is to either of the start methods or the onBind() method, we make a couple of quick initialization calls, but no background processing is started. Even this might be too much if neither of these objects were used by the interface provided by the binder.

Because we can’t always predict what version of Android our code is running on, we can simple implement both the onStart() and onStartCommand() methods and have them call a third method that provides a common implementation. This enables us to customize behavior on later Android versions while being compatible with earlier versions. To do this, the project needs to be built for an SDK of Level 5 or higher, while having a minSdkValue of whatever earlier versions are supported. Of course, we highly recommend testing on multiple platform versions to verify that the behavior is as you expect. Here are sample implementations of the onStartCommand() and onStart() methods:

@Override
public int onStartCommand(Intent intent, int flags, int startId ) {
Log.v(DEBUG_TAG, “onStartCommand() called, must be on L5 or later”);
if (flags != 0) {
Log.w(DEBUG_TAG, “Redelivered or retrying service start: “+flags);
}
doServiceStart(intent, startId);
return Service.START_REDELIVER_INTENT;
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.v(DEBUG_TAG, “onStart() called, must be on L3 or L4”);
doServiceStart(intent,startId);
}

Next, let’s look at the implementation of the doStartService() method in greater detail:

@Override
public void doServiceStart(Intent intent, int startId) {
super.onStart(intent, startId);
updateRate = intent.getIntExtra(EXTRA_UPDATE_RATE, -1);
if (updateRate == -1) {
updateRate = 60000;
}
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.NO_REQUIREMENT);
criteria.setPowerRequirement(Criteria.POWER_LOW);
location = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
String best = location.getBestProvider(criteria, true);
location.requestLocationUpdates(best,
updateRate, 0, trackListener);
Notification notify = new
Notification(android.R.drawable.stat_notify_more,
“GPS Tracking”, System.currentTimeMillis());
notify.flags |= Notification.FLAG_AUTO_CANCEL;
Intent toLaunch = new Intent(getApplicationContext(),
ServiceControl.class);
PendingIntent intentBack =
PendingIntent.getActivity(getApplicationContext(),
0, toLaunch, 0);
notify.setLatestEventInfo(getApplicationContext(),
“GPS Tracking”, “Tracking start at “ +
updateRate+”ms intervals with [“ + best +
“] as the provider.”, intentBack);
notifier.notify(GPS_NOTIFY, notify);
}

The background processing starts within the two start methods. In this example, though, the background processing is actually just registering for an update from another service. For more information about using location-based services and the LocationManager, see Chapter “Using Location-Based Services (LBS) APIs,” and for more information on Notification calls, see Chapter “Working with Notifications.”

In this case, we turn on the GPS for the duration of the process, which might affect battery life even though we request a lower power method of location determination. Keep this in mind when developing services.

The Intent extras object retrieves data passed in by the process requesting the service. Here, we retrieve one value, EXTRA_UPDATE_RATE, for determining the length of time between updates. The string for this, update-rate, must be published externally, either in developer documentation or in a publicly available class file so that users of this service know about it.

The implementation details of the LocationListener object, trackListener, are not interesting to the discussion on services. However, processing should be kept to a minimum to avoid interrupting what the user is doing in the foreground. Some testing might be required to determine how much processing a particular phone can handle before the user notices performance issues.

There are two common methods to communicate data to the user. The first is to use Notifications. This is the least-intrusive method and can be used to drive users to the application for more information. It also means the users don’t need to be actively using their phone at the time of the notification because it is queued. For instance, a weather application might use notifications to provide weather updates every hour.

The other method is to use Toast messages. From some services, this might work well, especially if the user expects frequent updates and those updates work well overlaid briefly on the screen, regardless of what the user is currently doing. For instance, a background music player could briefly overlay the current song title when the song changes.

The onDestroy() method is called when no clients are bound to the service and a request for the service to be stopped has been made via a call to the Context. stop Service() method, or a call has been made to the stopSelf() method from within the service. At this point, everything should be gracefully cleaned up because the service ceases to exist.

Here is an example of the onDestroy() method:

@Override
public void onDestroy() {
if (location != null) {
location.removeUpdates(trackListener);
location = null;
}
Notification notify = new
Notification(android.R.drawable.stat_notify_more,
“GPS Tracking”, System.currentTimeMillis());
notify.flags |= Notification.FLAG_AUTO_CANCEL;
Intent toLaunch = new Intent(getApplicationContext(),
ServiceControl.class);
PendingIntent intentBack =
PendingIntent.getActivity(getApplicationContext(),
0, toLaunch, 0);
notify.setLatestEventInfo(getApplicationContext(),
“GPS Tracking”, “Tracking stopped”, intentBack);
notifier.notify(GPS_NOTIFY, notify);
super.onDestroy();
}

Here, we stop updates to the LocationListener object. This stops all our background processing. Then, we notify the user that the service is terminating. Only a single call to the onDestroy() method happens, regardless of how many times the start methods are called. The system does not know about a service unless it is defined within the AndroidManifest.xml permissions file using the <service> tag. Here is the <service> tag we must add to the Android Manifest file:

<service
android:enabled=”true”
android:name=”GPXService”>
<intent-filter>
<action android:name=
“com.androidbook.GPXService.SERVICE” />
</intent-filter>
</service>

This block of XML defines the service name, GPXService, and that the service is enabled. Then, using an Intent filter, we use the same string that we defined within the class. This is the string that is used later on when controlling the service. With this block of XML inside the application section of the manifest, the system now knows that the service exists and it can be used by other applications.



Face Book Twitter Google Plus Instagram Youtube Linkedin Myspace Pinterest Soundcloud Wikipedia

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Android Topics