Understanding Android Services: An Overview of Service Components
Android services play a crucial role in app development by allowing tasks to run in the background without requiring user interaction. They facilitate communication between app components, perform long-running operations, and expose app functionality to other applications. This comprehensive guide covers the basics of Android services, their features, and common use cases.
Download Presentation
Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
E N D
Presentation Transcript
Cosc 5/4730 Android Services, JobServices, and WorkManager
Reminder Android applications normally have one or more of the following: Activity/fragment Provides a screen which a user interacts with. Service an application component that can perform long-running operations in the background without a user interface BroadcastReceiver This is way to receive information from other applications and the OS. ContentProvider You app is providing information to another app and itself via a encapsulated data structure
What is a service? From android developer web pages: Most confusion about the Service class actually revolves around what it is not: 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 (to avoid Application Not Responding errors). Thus a Service itself is actually very simple, providing two main features: A facility for the application to tell the system about something it wants to be doing in the background (even when the user is not directly interacting with the application). This corresponds to calls to Context.startService(), which ask the system to schedule work for the service, to be run until the service or someone else explicitly stop it. A facility for an application to expose some of its functionality to other applications. This corresponds to calls to Context.bindService(), which allows a long-standing connection to be made to the service in order to interact with it. http://developer.android.com/reference/android/app/Service.html
What is a service? (2) Basically a service can be though of as a data structure that runs. It doesn t need a screen Normally communicates with an activity in the application. It can run in parallel with an activity providing data and stuff. (binding) it may run without activity, to provide data for later use. Say an alarm starts it every X minutes to check on something. Then may use a handler, notification, call a broadcast receiver, or even start an activity. Or my just write out the data to local storage, for later use.
What is a service? (3) Example Use clicks on a picture that they want to download from the web into their gallery. The application kicks off a downloader service and then the user continues. The service downloads the picture and puts into the gallery. And creates a Notification when done that the picture has completed (or failed). The user can click on the notification and open the picture (using the gallery app).
What is a service (4) Starting a service Your app can start a service with startService call. The service will then run in the background You are responsible for stopping it Either stopself() (in the service) or stopService in the app. Binding to a service Your app is bound to the service (and it s started), normally with a RPC, with bindService The service returns a IBinder method, which allows the app communicate directly with the service. If you service won t allow binding, then the IBinder returns null.
What is a service? (5) Service This is the base class for all services. When you extend this class, it's important that you create a new thread in which to do all the service's work, because the service uses your application's main thread, by default, which could slow the performance of any activity your application is running. IntentService This is a subclass of Service that uses a worker thread to handle all start requests, one at a time. This is the best option if you don't require that your service handle multiple requests simultaneously. All you need to do is implement onHandleIntent(), which receives the intent for each start request so you can do the background work. You can override other methods as needed like you would need in a Service.
IntentService Easy to implement Create a constructor with a super("name") Override onHandleIntent(Intent) { } Inside is the work to be done. The Extra bundle tells you what "to process". Send broadcast intent or notification when "completed". May also send a message back to the activity via handler, by putting the messenger object in the Bundle!
IntentService Example public class myIntentService extends IntentService { required constructor public myIntentService() { super( myIntentService"); } Where we do the work. @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); //now get the information you need to do whatever is needed. } } See the myIntentService.java for the compete code. In the service repo, serviceDemo example
Calling the IntentService From the application we create an intent and then start the service. The example service returns X number of random numbers based on the intent, so Intent number5 = new Intent(getBaseContext(), myIntentService.class); number5.putExtra("times", 5); //5 random number And we want it to send numbers back through a messenger (handler) Messenger messenger = new Messenger(handler); number5.putExtra("MESSENGER", messenger); As note, If there is no MESSENGER key, then the service will use notifications. And finally start the service, using the intent that was created startService(number5);
Service. Far more complex. Need to create thread for it The serviceHandler as well Onstartcommand which will get the intent and then pass the information onto the servicehandler (via a messenger) so it off on it s own thread. You can also setup the IBinder as well. Well look at the template for the service code next.
Service code public class myService extends Service { private Looper mServiceLooper; private ServiceHandler mServiceHandler; @Override public void onCreate() { // Start up the thread running the service. Note that // we create a separate thread because the service // normally runs in the process's main thread, which we // don't want to block. We also make it // background priority so CPU-intensive work will not // disrupt our UI. //our global variables here. // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); @Override public void handleMessage(Message msg) { //our code here, to the work based on the msg. // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } See the myService.java for the compete code. In the service repo, serviceDemo example
Service code (2) @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; mServiceHandler.sendMessage(msg); // If we get killed, don t restart, wait for a startservice() to startup again. return START_NOT_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
Service code (3) In the App Intent intent = new Intent(this, myService.class); startService(intent); The startService() method returns immediately and the Android system calls the service's onStartCommand() method. If the service is not already running, the system first calls onCreate(), then calls onStartCommand().
Service code example. I m using the template code from before and adding to it where listed in red text. I copied the code from the developer site http://developer.android.com/guide/components/services.html#Exte ndingService You may need to initialize some things in the OnCreate() and/or OnStartCommand( ) as well.
ServiceDemo Remember a service, is just like an activity, except there is no screen. So most of the Demo code is downloading files and using file I/O and the notification system. Nothing really amazing at this point. When you need a service, you start it with an intent and the startService(intent) command. Just like you would an activity. The service ends when they are done and what for the next call.
API 26+ and services. Background Execution limits Background services are now limited. Any background service with an activity running is allowed Once the activity is done or pushed into the background, the service is killed. Any "foreground" service is allowed. This is started in the foreground and have a persistent notification attached to it. High-priority Firebase Cloud Messages (not normal priority) Executing of a pentingItent from a notification is allowed for a short period, roughly 5 seconds. Use JobSchedulers or the new WorkManager.
Foreground services From the activity/receiver (API 26+ method) startForegroundService(Intent i); You have a few seconds in the service to do the following: So do it first. Build a persistent notification (don't send it). startForeground(int ID, notification); A note, in Androidx, startForegroundService also requires a (non dangerous) <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> in the manifest file. See the foregroundServiceDemo in service repo
Api 33 and Toasts Services have no UI/screen. You may only be able to communicate (or debug) via log.x and toasts. Starting in API 33 (android 13), Toasts from the background are considered notifications, which are turned off by default. androidmanifest.xml file <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> ask for permission like you would for all the other permissions in an activity. Can t do it in the service. You don t need a channel like you do for actual notifications.
AIDL Android Interface Definition Language (AIDL) similar to other IDLs if you have worked with them before. It allows you to define the programming interface that both the client and service agree upon in order to communicate with each other using interprocess communication (IPC). We are not covering AIDL, in this class http://developer.android.com/guide/components/aidl.html
Bound Services A bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication (IPC). You need to implement the onBind() method and return a IBinder an IBinder object. The activity uses the object to call into the service. Or get a handler and send messages to the service. You can also use the AIDL as well.
Binder In it s simplest form, you allow the activity to call methods in the running service via the binder service. Instead of startService BindService(intent, ServiceConnection, flags) Now you use the ServiceConnection variable to call into the service to retrieve data or cause the service to do something.
Binder implementation In your service, create an instance of Binder that either: contains public methods that the client can call returns the current Service instance, which has public methods the client can call or, returns an instance of another class hosted by the service with public methods the client can call Return this instance of Binder from the onBind() callback method. In the Activity/fragment/whatever, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided. Let's look at the example code for see how the pieces go together ServiceDemoIPC uses binder so the activity can use its methods ServiceDemoMSG uses the binder to setup a handler to send messages to the service.
Manifest file. Like everything else services must be registered listed in the AndroidManifest.xml Uses the <service> tag and is pretty simple. Example: <service android:name=".myIntentService android:enabled="true" android:exported="true"> </service>
Example code. The ServiceDemo One example intent service for random numbers One Example Service for random numbers You can compare the complexity of a service with an intentService fileDlService is an intentService. It takes a URL (http://...) to down a picture and stores in the SD card downloads directory. When completed it sends a notification, so the user can open the file in the gallery viewer.
Example code (2) ServiceDemoIPC Uses a ServiceConnection to allow the activity to call into the service to get a random number Based on Googles code. ServiceDemoMSG Setups a handler to send messages to a service This service will toast a message. But you can easily change that to have the service do many difference things, based on the message.
References http://developer.android.com/reference/android/app/Service. html http://www.vogella.com/articles/AndroidServices/article.html http://developer.android.com/guide/components/services.htm l http://developer.android.com/guide/components/aidl.html http://developer.android.com/guide/components/bound- services.html
Job Services There is a JobIntentService and a JobService JobIntentService is like a IntentService and it is located androidx.core androidx.core.app.JobIntentService JobService starts in API 21, more added in 23, plus new workItems in 26, but is not in androidx Android 11 offers debugging support for apps to identify potential JobScheduler API invocations that have exceeded certain rate limits. Developers can use this facility to identify potential performance issues. For apps with the debuggable manifest attribute set to true, JobScheduler API invocations beyond the rate limits will return RESULT_FAILURE. Limits are set such that legitimate use cases should not be affected.
JobIntentService public class MyJobIntentService extends JobIntentService { @Override protected void onHandleWork(Intent intent) { We have received work to do. The system or framework is already holding a wake lock for us at this point, so we can just go. } Convenience method for enqueuing work in to this service. Call this method, with an intent and it will start up the job. static void enqueueWork(Context context, Intent work) { enqueueWork(context, MyJobIntentService.class, JOB_ID, work); } }
JobService JobService requires a JobInfo to be built. Give a time frame to run in and if any events are involved. Such as run this job when the device when it on the charger. Like the standard Service there are a number of parts to jobservice class
Example code There is a JobIntentService and JobService example code These produce simple random numbers Gives you a framework of both the services.
Architecture WORKMANAGER
Schedule tasks with WorkManager The WorkManager API makes it easy to specify deferrable, asynchronous tasks and when they should run. These APIs let you create a task and hand it off to WorkManager to run immediately or at an appropriate time. For example, an app might need to download new resources from the network from time to time. Using these classes, you can set up a task, choose appropriate circumstances for it to run (like "only while device is charging and online"), and hand it off to WorkManager to run when the conditions are met. The task is still guaranteed to run, even if your app is force-quit or the device is rebooted. You can check a task's state and its return vales by observing its LiveData and update the UI for status. https://developer.android.com/topic/libraries/architecture/workmanager
adding to your project implementation 'androidx.work:work-runtime:2.2.0' There used to be firebase job scheduler part, but it been fulling subsumed into the Worker and ListenableWorker
Components and concepts. Worker: the app extends the Abstract Worker class to perform the work here. WorkRequest: specifies which worker class should perform the task. Specific information such as when and what circumstances to run as well. There is a WorkRequest.Builder WorkManager: enqueues and manages the work requests. The manager will schedule the task WorkStatus gives info about a task. WorkManager provides a LiveData for each WorkRequest . The liveData holds the WorkStatus object. You can observe the LiveData to determine status.
Running tasks. A task can be "OneTimeWorkRequest" or a recurring task. Recurring tasks use a PeriodicWorkRequest that specifices how often the task is run, say once every 24 hours. We can chain tasks together as well. Say you need to run A, B, then C. Or run some in parallel as well, so run A1 and A2, then B, then C1 and C2. Or even more complex chains of tasks.
Work example The WorkManagerDemo has examples one shot, ie run a task. sending parameters to a task and getting results. a chain of workers A and B (in parallel), and worker C waiting until both are complete.
References https://developer.android.com/about/versions/oreo/background.html https://www.intertech.com/Blog/android-development-tutorial-job-scheduler/ https://developer.android.com/reference/android/app/job/JobScheduler.html https://developer.android.com/reference/android/app/job/JobWorkItem.html API 26+ allows you enqueue and then dequeuer intents as job items https://developer.android.com/reference/android/app/job/JobParameters.html#dequeu eWork() http://www.vogella.com/tutorials/AndroidTaskScheduling/article.html https://github.com/googlesamples/android-JobScheduler https://developer.android.com/topic/libraries/architecture/workmanager
QA &