Android Services ITAY ARIEL ASAF VALADARSKY LIOR BAR
Android Services ITAY ARIEL ASAF VALADARSKY LIOR BAR
Topics We Will Cover �Introduction to services. �Useful subtypes of services: Intent services. Bounded services. �Android Interface Definition Language (AIDL). �An example.
Topics We Will Not Cover �Backward capabilities. �Using Alarm. Manager to start a service periodically. �All those appear at the end of the presentation.
Introduction
What Are Services? �A service is an application component that can perform long-running operations in the background and does not provide a user interface. �A service can allow other components to bind to it, in order to interact with it and perform interprocess communication (IPC). �Basically allows you to communicate with an application, without the need for it to be in the foreground.
What is it good for anyways? �Long running tasks Downloading a file. Playing music. Syncing to cloud. �Using system provided services (USB, Location, Phone, Power etc. . ) Access to them can be gained via the get. System. Service() method. �Interacting through status bar notifications. �Isn’t it better to use threads instead? That depends, if you need to perform the task only when the application is available – then yes, otherwise if you want your task to run without the application being visible – then no.
Services 101
Declaring a service - 1 �Like activities (and other components), you must declare all services in your application's manifest file, by adding the tag <service> in under the application tag, like so: <manifest. . . > . . . <application. . . > <service android: name=". Service. Name" /> . . . </application> </manifest> �There are other attributes you can include in the <service> element to define properties such as permissions required to start the service, the process in which the service should run and if it should run in a separate process.
Declaring a service - 2 �Like activities, services can define intent-filters which allows other components to invoke the service using implicit intents. �If you plan that you are to be the only one to use your service, you should not supply any intent filter. Thus you must start you service using an intent which implicitly states the service name. Additionally, you can ensure that your service is private to your application only if you include the android: exported attribute and set it to "false". This is effective even if your service supplies intent filters.
Important To Note. . . � A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of. � A Service is not a thread. It is not a means itself to do work off of the main thread. � After creating a service and publishing your application – you cannot change the service name, as it could break applications depending on it. unless you are declaring your service private – discussed later on. � The service runs indefinitely in the background, even if the component that started it is destroyed. � So when doing heavy work on a service, you should spawn new threads to do that work, or use Intent. Service (discussed later on). � If you want your service to be available to other applications, it must run in it’s own process (providing garbage collector, memory address space etc).
How To Create A Service �To create a service, you must create a subclass of the Service class (or one of its existing subclasses). �The most important (and necessary) methods are: on. Start. Command()– Being called when the service is started using the start. Service() method. � You should return an int here to let the system know how to handle your service when it’s killed. on. Bind() – later on. Create() - The system calls this method when the service is first created, if the service is already running, this method is not called. on. Destroy() – Important! You should use this method to clean up all resources your service used (threads, listeners etc. )
Client Side �Starting the service - To start a service you need to invoke start. Service(). This method returns immediately. If you want your service to send results back to you, use Pending. Intent(using broadcast mechanism). �Stopping the service - Because a service can run indefinitely, it should stop itself when all work is done (using stop. Self() ) or be stopped by another application component using stop. Service().
Life Cycle � The active lifetime of a service begins with a call to either on. Start. Command() or on. Bind(). � Although a started service is stopped by a call to either stop. Self() or stop. Service(), there's no on. Stop() (like in activity). So, unless the service is bound to a client, the system destroys it when the service is stopped. � on. Destroy() is the only callback received.
Intent Service
Intent. Service - 1 �An application component such as an activity can start the service by calling start. Service() and passing an Intent that specifies the service and includes any data for the service to use. The service receives this Intent in the on. Start. Command() method. �Because most services don’t need to handle multiple requests at a time, you should use this super-class rather than the Service.
Intent. Service - 2 �Why should you use Intent. Service? Well because it: Creates a default worker thread that executes all intents delivered to on. Start. Command() separate from your application's main thread! Creates a work queue that passes one intent at a time to your on. Handle. Intent() implementation (so you never have to worry about multi-threading). Stops the service after all start requests have been handled. Provides default implementation of on. Bind() that returns null. Provides a default implementation of on. Start. Command() that sends the intent to the work queue and then to your on. Handle. Intent() implementation. �on. Handle. Intent() – Is all you need to do.
Creating A Simple Service �If you decide to also override other callback methods, such as on. Create(), on. Start. Command(), or on. Destroy(), don’t forget to call the super implementation. public class Basic. Service extends Intent. Service { public Basic. Service(){ super(“Basic. Service”); } @Override protected void on. Handle. Intent(Intent intent) { //Handle the intent } }
Notifications �A service can notify the user when some work has been done. Usually a Status-Bar notification is the most preferred technique for background services as it allows for greater interaction with the user. Can pop a Toast notification as well. �Using a status bar notification can start an activity, which could be great for a music player, file downloads etc.
Foreground vs. Background �A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory. �A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading. Meaning that the notification cannot be dismissed unless the service is either stopped or removed from the foreground. �To request that your service run in the foreground, call start. Foreground(). This method takes two parameters: an integer that uniquely identifies the notification and the Notification for the status bar (which again should be persistent). �To remove the service from the foreground, call stop. Foreground().
Foreground Example �This is how you usually start your service in the foreground: Notification notification = new Notification(R. drawable. icon, get. Text(R. string. ticker_text), System. current. Time. Millis()); Intent noti. Intnet = new Intent(this, Example. Activity. class); Pending. Intent pending. Intent = Pending. Intent. get. Activity(this, 0, noti. Intnet, 0); notification. set. Latest. Event. Info(this, get. Text(R. string. notification_title), get. Text(R. string. notification_message), pending. Intent); start. Foreground(ONGOING_NOTIFICATION, notification);
Bounded Service
Definition A bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service in order to: �send requests. �receive responses. �perform interprocess communication (IPC).
Two Bounded Services �There are two kinds of bounded service: Private service for your process � Create your own interface by extending the Binder class � The client receives the Binder and can use it to directly access public methods available in either the Binder implementation or even the Service that serve many processes � Concurrency not needed: Use a Messenger. � Concurrency needed: Use AIDL (Android Interface Definition Language).
Bounded Service implementation �bind. Service() – the client bind to the service by calling this. �Service. Connection – the client must provide an implementation of a Service. Connection �on. Bind – you must implement this method in the server. The on. Bind returns an instance of an Ibinder. �Ibinder - specifies the interface in which applications can interact with the service.
Service Activity Relationship bind. Service(service. Con) on. Bind() IBinder on. Service. Connected (Ibinder) f on. Service. Disconnected play. Music() on. Destroy() Ibinder. get. Service(). play. Music() un. Bind. Service()
Service Side public class My. Binder extends Binder { Music. Service get. Service() { return Music. Service. this; } } private final IBinder m. Binder = new My. Binder(); public IBinder on. Bind(Intent arg 0) { return m. Binder; }
Activity Side private Music. Service m. Serv; Intent intent = new Intent(this, Music. Service. class); bind. Service(intent, Scon, Context. BIND_AUTO_CREATE); private Service. Connection Scon =new Service. Connection(){ public void on. Service. Connected(Component. Name name, Ibinder) { m. Serv = ((Music. Service. Binder)binder). get. Service(); } public void on. Service. Disconnected(Component. Name name) { m. Serv = null; } }; m. Serv. resume. Music(); m. Serv. pause. Music();
Messenger - 1 �Used for communication between the service and the process binding to it (and possibly other processes which bind to the service). No need for AIDL (In a moment) �How to use a messenger – general scheme: The service implements a Handler that receives a callback for each call from a client. The Handler is used to create a Messenger object (which is just a reference to the Handler object). The Messenger creates an IBinder that the service returns to clients from on. Bind(). Clients use the IBinder to instantiate the Messenger in which the client uses to send Message objects to the service. The service receives each Message in its handle. Message() method (which is inside the Handler object).
Messenger – 2 �Server Side: public class Messenger. Service extends Service { static final int SAY_MSG = 1; class Incoming. Handler extends Handler { @Override public void handle. Message(Message msg) { //handle message code } } final Messenger m. Messenger = new Messenger(new Incoming. Handler()); @Override public IBinder on. Bind(Intent intent) { Toast. make. Text(get. Application. Context(), "binding", Toast. LENGTH_SHORT). show(); return m. Messenger. get. Binder(); } }
Messenger – 3 �Client Side: //Create connection to service as seen before, only now create a messenger public void say. Msg() { if (!m. Bound) return; // Create and send a message to the service, using a supported 'what' value Message msg = Message. obtain(null, Messenger. Service. SAY_MSG, 0, 0); try { m. Service. send(msg); } catch (Remote. Exception e) { e. print. Stack. Trace(); } } ….
Android Interface Definition Language (AIDL)
What Is AIDL? �IDL (By Wikipedia): Is a specification language used to describe a software component's interface. �It allows you to define the programming interface that both the client and service agree upon in order to communicate with each other using IPC. �Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. Only use it if you are sure you cannot achieve it using Messenger and BInder.
AIDL - 1 �You must define your AIDL interface in an. aidl file using the Java programming language syntax, then save it in the source code (in the src/ directory). Of both the application hosting the service and any other application that binds to the service. �When you build each application that contains the . aidl file, the Android SDK tools generate an IBinder interface based on the. aidl file and save it in the project's gen/ directory.
AIDL - 2 �To create a bounded service using AIDL: Create the. aidl file This file defines the programming interface with method signatures. Implement the interface based on your. aidl file. This interface has an inner abstract class named Stub that extends Binder and implements methods from your AIDL interface. � You must extend the Stub class and implement the methods. Expose the interface to clients, implement a Service and override on. Bind() to return your implementation of the Stub class. �More in the Android API.
Resources �A good tutorial �IBinder API �Service manifest �Services API �AIDL Developer �Accessing System Guidelines �IDL By Wikipedia �Services Developer Guidelines �Bounded Services Developer Guidelines Services
Thank You!
There’s Even More!
Bounder Service Life Cycle � When a service is unbound from all clients, the system destroys it. unless it was also started with on. Start. Command(). � If you chose to implement the on. Start. Command() method then you must explicitly stop the service. In this case, the service runs until the service stops itself with stop. Self() or another component calls stop. Service().
Things We Did Not Cover - 1 �Backward capability – If you want to support android versions you should use different signatures for some of the methods, appears in the API.
Things We Did Not Cover - 2 �You can start a service with the system’s alarm manager, which starts it periodically. Because the system can kill it at any give moment you cannot use Timer. Task (which is the same mechanism, but for activities) Intent intent = new Intent(this, My. Service. class); Pending. Intent pintent = Pending. Intent. get. Service(this, 0, intent, 0); Alarm. Manager alarm = (Alarm. Manager)get. System. Service(Context. ALARM_SERVICE); // Start every 30 seconds alarm. set. Repeating(Alarm. Manager. RTC_WAKEUP, cal. get. Time. In. Millis(), 30*1000, pintent);
- Slides: 40