Android Services Mobile Application Development Selected Topics CPIT
Android Services Mobile Application Development Selected Topics – CPIT 490 07 -Sep-21
Objective n Working in Background n Services n Broadcast. Receiver n Async. Task 2
Android Application Components n n n n Activity Views Service Broadcast Receiver Content Provider Intents Widgets 3
Services n n n A Service is an application component that runs in the background, not interacting with the user, for an indefinite period of time. 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). Higher priority than inactive Activities, so less likely to be killed n If killed, they can be configured to re-run automatically (when resources available) If a service and the respective activity are run on the same thread, then the activity will become unresponsive when the service is being executed Each service class must have a corresponding <service> declaration in its package's Android. Manifest. xml n <service android: name=”. My. Service” /> To make service available to other applications n <service android: name=”. My. Service”> n <intent-filter> <action android: name=”net. learn 2 develop. My. Service” /> n </intent-filter> </service> 4
Services n n Services can be started with Context. start. Service() and Context. bind. Service() in the main thread of the application’s process. n CPU intensive tasks must be offloaded to background threads using Thread or Async. Task n start. Service(new Intent(get. Base. Context(), My. Service. class)); n start. Service(new Intent(“net. learn 2 develop. My. Service”)); To stop a service: stop. Service(new Intent(get. Base. Context(), My. Service. class) or stop. Self() Alarms can be used to fire Intents at set times. These can start services, open Activities, or broadcast Intents The written services class should extend Service class and has three methods n public IBinder on. Bind(Intent arg 0) {. . . } n public int on. Start. Command(Intent intent, int flags, int start. Id) {. . . } n public void on. Destroy() {. . . } 5
Creating a Service n n Subclass Service, then override: n on. Start. Command() -- called when start. Service() is called. Then you can call stop. Self() or stop. Service() n on. Bind() -- called when bind. Service() is called. Returns an IBinder (or null if you don't want to be bound). n on. Create() -- called before above methods. n on. Destroy() -- called when about to be shut down. There are two classes you can subclass: n Service: you need to create a new thread, since it is not created by default. n Intent. Service. This uses a worker thread to perform the requests, and all you need to do is override on. Handle. Intent. This is the easiest, provided you don't need to handle multiple requests. 6
Services Lifecycle n n n A Service has three lifecycle methods: n 1. void on. Create() n 2. void on. Start. Command() n 3. void on. Destroy() on. Start. Command() is invoked when a service is explicitly started using start. Service() method on. Destroy() is invoked when a service is stopped using stop. Service() method 7
Services Lifecycle n n n To handle a block for code for specified time period, use Timer class within the service n private void do. Something. Repeatedly() { n timer. schedule. At. Fixed. Rate(new Timer. Task() { n public void run() { Log. d(“My. Service”, String. value. Of(++counter)); } n }, 0, UPDATE_INTERVAL); } You passed an instance of the Timer. Task class to the schedule. At. Fixed. Rate() method so that you can execute the block of code within the run() method repeatedly The second parameter to the schedule. At. Fixed. Rate() method specifies the amount of time, in milliseconds, before first execution The third parameter specifies the amount of time, in milliseconds, between subsequent executions Timer. Task class itself implements Runnable interface and thus can be run on a separate thread. So, no need to wrap it in Async. Task class 8
Creating a Service import android. app. Service; import android. content. Intent; import android. os. IBinder; public class My. Service extends Service { @Override public void on. Create() { // TODO: Actions to perform when service is created. } @Override public IBinder on. Bind(Intent intent) { // TODO: Replace with service binding implementation. return null; } @Override public int on. Start. Command(Intent intent, int flags, int start. Id) { // TODO Launch a background thread to do processing. return Service. START_STICKY; } @Override public void on. Destroy () { // TODO: Actions to perform when service is ended. } } 9
on. Start. Command n Called whenever the Service is started with start. Service call n So beware: may be executed several times in Service’s lifetime! n Controls how system will respond if Service restarted n (START_STICKY) means the service will run indefinitely until explicitly stopped n Run from main GUI thread, so standard pattern is to create a new Thread from on. Start. Command to perform processing and stop Service when complete 10
Starting a Service n n n n Call start. Service // Implicitly start a Service Intent my. Intent = new Intent(My. Service. ORDER_PIZZA) ; my. Intent. put. Extra("TOPPING", "Margherita"); start. Service(my. Intent) ; // Explicitly start a Service start. Service(new Intent(this, My. Service. class)) ; (To use this example, would need to include a ORDER_PIZZA constant in My. Service class and use an Intent Filter to register the Service as a provider of ORDER_PIZZA) 11
Stopping a Service n n n n n Call stop. Service Component. Name service = start. Service(new Intent(this, Baseball. Watch. class)) ; // Stop a service using the service name. stop. Service(new Intent(this, service. get. Class())); // Stop a service. // try { // Class service. Class = Class. for. Name(service. get. Class. Name()); // stop. Service(new Intent(this, service. Class)); // } catch (Class. Not. Found. Exception e) {} 12
Passing Data b/w service & activity n n n n public void start. Service(View view) { Intent intent = new Intent(get. Base. Context(), My. Service. class); try { URL[] urls = new URL[] { new URL(“http: //www. amazon. com/somefiles. pdf”), new URL(“http: //www. wrox. com/somefiles. pdf”), intent. put. Extra(“URLs”, urls); } catch (Malformed. URLException e) { e. print. Stack. Trace(); } start. Service(intent); } // use Bundle to pass data between activitiy and service public int on. Start. Command(Intent intent, int flags, int start. Id) { // in service side Object[] obj. Urls = (Object[]) intent. get. Extras(). get(“URLs”); URL[] urls = new URL[obj. Urls. length]; // In Java, casting from one array type to another is not possible directly. Thus do for each element for (int i=0; i<obj. Urls. length-1; i++) { urls[i] = (URL) obj. Urls[i]; } new Do. Background. Task(). execute(urls); return START_STICKY; } 13
Binding Activities to Services n n n Activity maintains reference to a Service Activity can make calls on the Service just as any other instantiated class. Thus an activity can directly access members and methods inside a service To support this, implement on. Bind for the Service (in Service part) // create an instance of the My. Binder class private final IBinder binder = new My. Binder(); // override the on. Bind() method to return the My. Binder instance @Override public IBinder on. Bind(Intent intent) { return binder; } // create an inner class that extends Binder class and implement get. Service() method public class My. Binder extends Binder { My. Service get. Service() { return My. Service. this; } } 14
Binding Activities to Services n n In on. Start. Command() method (in service part) n new Do. Background. Task(). execute(urls); In Activity part n Create instance of service and intent n My. Service service. Binder; n Intent i; n Monitor the state of the service using an instance of Service. Connection class n The on. Service. Connected() method is called when the activity is connected to the service n The on. Service. Disconnected()method is called when the service is disconnected from the activity. 15
Binding Activities to Services n n n In on. Service. Connected() method, get the instance of service using get. Service() method and assign it to service. Binder object Bind the activity to the service n public void start. Service(View view) { n i = new Intent(Services. Activity. this, My. Service. class); n bind. Service(i, connection, Context. BIND_AUTO_CREATE); } bind. Service has three arguments: an Intent object, a Service. Connection object, and a flag to indicate how the service should be bound Start the service with start. Service(intentobject) using an intent object Once Service is bound, all public methods and properties are available through the service. Binder object obtained from the on. Service. Connected handler 16
Binding Activities to Services private My. Service service. Binder; // Reference to the service // Handles the connection between the service and activity private Service. Connection m. Connection = new Service. Connection() { public void on. Service. Connected(Component. Name class. Name, IBinder service) { // Called when the connection is made. service. Binder = ((My. Service. My. Binder)service). get. Service(); } public void on. Service. Disconnected(Component. Name class. Name) { // Received when the service unexpectedly disconnects. service. Binder = null; } }; @Override public void on. Create(Bundle icicle) { super. on. Create(icicle); // Bind to the service Intent bind. Intent = new Intent(My. Activity. this, My. Service. class) ; bind. Service(bind. Intent, m. Connection, Context. BIND_AUTO_CREATE); } 17
Services n n Declare services in manifest Service Lifecycle: n on. Create, on. Start. Command, on. Destroy Can start services by passing in an intent similar to starting an activity Must stop service before starting up another instance n Best to start service in on. Create/on. Resume and stop in on. Pause 18
Background threads n n To make application responsive, move all time-consuming operations off main app thread to child thread. Very important! Two options: n Async. Task n n Create an inner class that extends Async. Task class. The Async. Task class enables handling of background execution without manually handling threads and handlers private class abc extends Async. Task<URL, Integer, Long> { The inner class has three methods: do. In. Background() has an array of first generic type (URL in this case) specified in abc as parameter and the third generic type (Long in this case) as the result; on. Progress. Update() accepts an array of 2 nd generic type (Integer in this case) as parameter; on. Post. Execute() accepts 3 rd generic type (Long in this case) as parameter Write own Threads 19
Async. Task<Params, Progress, Result> n Execution of asynchronous task goes through following main steps: n do. In. Background(Params. . . ): used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result will be passed to on. Post. Execute(). publish. Progress(Progress. . . ), which is invoked from do. In. Background(), is used to publish one or more units of progress by calling on. Progress. Update(Progress. . . ). n on. Progress. Update(Progress. . . ): invoked after a call to publish. Progress(Progress. . . ). Used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field. n on. Post. Execute(Result): invoked after the background computation finishes. The result of the background computation is passed to this step as a parameter. 20
Async. Task<Params, Progress, Result> n n n Pressing the back button in the emulator or device will close the activity but the task will keep on running To stop the Async. Task subclass, you need to get an instance of it first. To stop the task, call its cancel() method. Within the task, you call the is. Cancelled() method to check whether the task should be terminated public class Threading. Activity extends Activity { static Text. View txt. View 1; Do. Counting. Task task; public void stop. Counter(View view) { task. cancel(true); } private class Do. Counting. Task extends Async. Task<Void, Integer, Void> { protected Void do. In. Background(Void. . . params) { publish. Progress(i); … if (is. Cancelled()) break; } return null; } protected void on. Progress. Update(Integer. . . progress) { … } } protected void on. Pause() { super. on. Pause(); stop. Counter(txt. View 1); } 21
Creating Async. Task n n n n new Download. Files. Task(). execute(url 1, url 2, url 3); //this call in on. Start. Command() private class Download. Files. Task extends Async. Task<URL, Integer, Long> { @Override protected Long do. In. Background(URL. . . urls) { //Background thread. Do not interact with UI int my. Progress = 0; long result=0; // [. . . Perform background processing task, update my. Progress. . . ] Publish. Progress(my. Progress) // [. . . Continue performing background processing task. . . ] // Return the value to be passed to on. Post. Execute return result; } @Override protected void on. Progress. Update(Integer. . . progress) { //Post interim updates to UI thread; access UI // [. . . Update progress bar, Notification, or other UI element. . . ] } @Override protected void on. Post. Execute(Long result) { //Run when do. In. Background completed; access UI // [. . . Report results via UI update, Dialog, or notification. . . ] show. Dialog("Downloaded " + result + " bytes"); } } 22
Services using Intent. Service class n n n n n To easily create a service that runs a task asynchronously and terminates itself when it is done, you can use the Intent. Service class The Intent. Service class is a base class for Service that handles asynchronous requests on demand It is started just like a normal service; and it executes its task within a worker thread and terminates itself when the task is completed // Create a class that extends Intent. Service class instead of Service class public class My. Intent. Service extends Intent. Service { } // create a constructor and call superclass with the name of the intent service as a string public My. Intent. Service() { super(“My. Intent. Service. Name”); } // on. Handle. Intent() is executed on a worker thread protected void on. Handle. Intent(Intent intent) { … } 23
Services using Intent. Service class n n n n The Intent. Service class does the following: 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, so you never have to call stop. Self(). 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. All you have to do is handle on. Handle. Intent(). 24
Services using Intent. Service class public class Hello. Intent. Service extends Intent. Service { // A constructor is required, and must call the super Intent. Service(String) // constructor with a name for the worker thread. public Hello. Intent. Service() { super("Hello. Intent. Service"); } // The Intent. Service calls this method from the default worker thread with the intent that started // the service. When this method returns, Intent. Service stops the service, as appropriate. @Override protected void on. Handle. Intent(Intent intent) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long end. Time = System. current. Time. Millis() + 5*1000; while (System. current. Time. Millis() < end. Time) { synchronized (this) { try { wait(end. Time - System. current. Time. Millis()); } catch (Exception e) { } }}}} 25
Running a Service in Foreground n n To request running in foreground: start. Foreground() To remove from foreground: stop. Foreground() Notification notification = new Notification(R. drawable. icon, get. Text(R. string. ticker_text), System. current. Time. Millis()); Intent notification. Intent = new Intent(this, Example. Activity. class); Pending. Intent pending. Intent = Pending. Intent. get. Activity(this, 0, notification. Intent, 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); 26
Creating own threads n n n // write your own thread using Thread and Runnable class new Thread(new Runnable() { public void run() { // don’t update the UI directly from here because in Android updating UI from a separate thread wont work properly for (int i=0; i<=1000; i++) { txt. View 1. set. Text(String. value. Of(i)); } // WRONG // update using post method of any view with Runnable //---update UI like this --txt. View 1. post(new Runnable() { public void run() { … } }); } }). start(); Write the task within the run() method Start the Runnable block using the Thread class A Runnable is a block of code that can be executed by a thread 27
Creating own threads n n n n Updating from another thread is possible using Handler class A Handler enables you to send and process messages, similar to using the post() method of a View import android. os. Handler; //---used for updating the UI on the main activity--static Handler UIupdater = new Handler() { @Override public void handle. Message(Message msg) { byte[] buffer = (byte[]) msg. obj; //---convert the entire byte array to string--String str. Received = new String(buffer); //-display the text received on the Text. View--txt. View 1. set. Text(str. Received); public void start. Counter(View view) { new Thread(new Runnable() { @Override public void run() { //---update the main activity UI--Threading. Activity. UIupdater. obtain. Message(0, String. value. Of(i). get. Bytes() ). send. To. Target(); Refer: http: //developer. android. com/reference/android/os/Handler. html 28
Broadcast. Receiver n n Component that responds to system-wide broadcast announcements. Example system broadcasts: screen has turned off, the battery is low, user is present using phone, or a picture was captured. Applications can initiate broadcasts—e. g. , to let other applications know that some data has been downloaded to the device and is available for them to use. Don’t display a UI, but can create a status bar notification to alert the user when a broadcast event occurs. 29
Broadcast. Receiver n Usually, a broadcast receiver is just a "gateway" to other components and is intended to do a very minimal amount of work. For instance, it might initiate a service to perform some work based on the event. n Important: you must complete tasks in a Broadcast. Receiver within <10 s. If you have a task that will take longer, you must start a new thread to avoid application assassin OS. 30
Broadcast. Receiver Lifecycle n The system delivers a broadcast Intent to all interested broadcast receivers, which handle the Intent sequentially. 31
Broadcast. Receiver Lifecycle n n A broadcast receiver has a single callback method: void on. Receive(Context cur. Context, Intent broadcast. Msg) n n 1. When a broadcast message arrives to a receiver, Android calls its on. Receive() method and passes it the Intent object containing the message. 2. The broadcast receiver is considered to be active only while it is executing this method. 3. When on. Receive() returns, it is inactive. 32
Example • Starting Broadcast public static final String NEW_LIFEFORM_DETECTED = “com. paad. action. NEW_LIFEFORM”; Intent intent = new Intent(NEW_LIFEFORM_DETECTED); intent. put. Extra(“lifeform. Name”, lifeform. Type); send. Broadcast(intent); • Broadcast. Receiver import android. content. Broadcast. Receiver; import android. content. Intent; import android. content. Context; public class My. Broadcast. Receiver extends Broadcast. Receiver { @Override public void on. Receive( Context context, Intent intent) { //TODO: React to the Intent received. } } 33
Example 2 n n n n Starting Broadcast //---send a broadcast to inform the activity Intent broadcast. Intent = new Intent(); broadcast. Intent. set. Action(“FILE_DOWNLOADED_ACTION”); // only those activities listening for this intent will be invoked get. Base. Context(). send. Broadcast(broadcast. Intent); Broadcast. Receiver public void on. Resume() { super. on. Resume(); //---intent to filter for file downloaded intent--intent. Filter = new Intent. Filter(); intent. Filter. add. Action(“FILE_DOWNLOADED_ACTION”); //---register the receiver--register. Receiver(intent. Receiver, intent. Filter); } private Broadcast. Receiver intent. Receiver = new Broadcast. Receiver() { @Override public void on. Receive(Context context, Intent intent) { … } }; 34
Manifest n The manifest of applications using Android Services must include: n If the application defines a Broadcast. Receiver as an independent class, it must include a <receiver> clause identifying the component. In addition an <intent-filter> entry is needed to declare the actual filter the service and the receiver use. 35
Manifest n n n n n <? xml version = "1. 0" encoding = "utf-8" ? > <manifest xmlns: android = "http: //schemas. android. com/apk/res/android" package = "cs 495. demos" android: version. Code = "1“ android: version. Name = "1. 0. 0" > <uses-sdk android: min. Sdk. Version = "4" ></uses-sdk> <application android: icon = "@drawable/icon" android: label = "@string/app_name" > <activity android: name = ". My. Service. Driver 2“ > <intent-filter> <action android: name = "android. intent. action. MAIN" /> <category android: name = "android. intent. category. LAUNCHER" /> </intent-filter> </activity> <service android: name = “. My. Service 2" /> <receiver android: name = “. My. Broadcast. Receiver" > <intent-filter> <action android: name = "com. paad. action. NEW_LIFEFORM" /> </intent-filter> </receiver> 36 </application> </manifest>
Native Broadcasts n n n n n ACTION_BOOT_COMPLETED ACTION_CAMERA_BUTTON ACTION_DATE_CHANGED and ACTION_TIME_CHANGED ACTION_MEDIA_BUTTON ACTION_MEDIA_EJECT ACTION_MEDIA_MOUNTED and ACTION_MEDIA_UNMOUNTED ACTION_SCREEN_OFF and ACTION_SCREEN_ON ACTION_TIMEZONE_CHANGED For comprehensive list: http: //code. google. com/android/reference/android/content/Int ent. html 37
Device Power n n n Just because you have code in a Broadcast. Receiver or Service doesn’t mean it will run if the phone goes into a low-power state Common problem: create a Broadcast receiver. Create a thread from within it to run code. . All works fine when phone is on and plugged into computer during development Fails under normal use because phone shuts down quickly in power management state Need to use a Wake. Lock! 38
Wake. Lock n n Control the power state on device (somewhat) Used to n Keep the CPU running n Prevent screen dimming or going off n Prevent backlight from turning on Only use when necessary and release as quickly as possible Need to request the n android. permission. WAKE_LOCK permission in the <usespermission> element of the manifest file. 39
Creating a Wake. Lock n n n Power. Manager pm = (Power. Manager)get. System. Service(Context. POWER_SERVICE); Wake. Lock wake. Lock = pm. new. Wake. Lock(Power. Manager. PARTIAL_WAKE_LOCK, "My. Wake. Lock"); wake. Lock. acquire(); [. . . Do things requiring the CPU stay active. . . ] wake. Lock. release(); PARTIAL_WAKE_LOCK keeps the CPU running without the screen on 40
Project Ideas n n Security n ODU Secure Application Localization n Taking random pictures from your cell at home when it is on a table. Could you locate the phone using the ceiling feature? Medical/health/activity monitoring n Parkin's disease detection n EEG Set Transportation n Detecting and identifying whether group of people are on the same transport unit using correlation of accelerometer, gyro, etc 41
Project Ideas n n Education n Engineering management game Misc n Understanding Interface activities power consumption n Extension of Magno. Tricoder n Bird Sound Detection n n Last Year Projects: n http: //www. cs. odu. edu/~nadeem/classes/cs 495 F 11/projects. htm 42
Example 1. A very Simple Service n n n n The main application starts a service. The service prints lines on the DDMS Log. Cat until the main activity stops the service. // a simple service is started & stopped package cs 495. demos; import android. app. Activity; import android. content. Component. Name; import android. content. Intent; import android. os. Bundle; import android. view. View. On. Click. Listener; import android. widget. *; public class Service. Driver 1 extends Activity { Text. View txt. Msg; Button btn. Stop. Service; Component. Name service; Intent intent. My. Service; 43
Example 1 Contd… n n n n n @Override public void on. Create( Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. main); txt. Msg= ( Text. View ) find. View. By. Id(R. id. txt. Msg); intent. My. Service = new Intent(this, My. Service 1. class); service = start. Service(intent. My. Service); btn. Stop. Service= ( Button ) find. View. By. Id(R. id. btn. Stop. Service); btn. Stop. Service. set. On. Click. Listener( new On. Click. Listener() { public void on. Click( View v) { try { stop. Service((intent. My. Service)); txt. Msg. set. Text("After stoping. Service: n" + service. get. Class. Name()); } catch (Exception e) { Toast. make. Text(get. Application. Context(), e. get. Message(), 1). show(); } } } ); } } 44
Example 1 Contd… Service n n n n n //non CPU intensive service running the main task in its main thread package cs 495. demos; Import android. app. Service; Import android. content. Intent; Import android. os. IBinder; Import android. util. Log; public class My. Service 1 extends Service { @Override public IBinderon. Bind(Intent arg 0) { return null ; } @Override public void on. Create() { super. on. Create(); Log. i("<<My. Service 1 -on. Start>>", "I am alive-1!"); @Override public void on. Start(Intent intent, intstart. Id) { super. on. Start(intent, start. Id); Log. i("<<My. Service 1 -on. Start>>", "I did something very quickly"); @Override public void on. Destroy() { super. on. Destroy(); Log. i("<<My. Service 1 -on. Destroy>>", "I am dead-1"); } }//My. Service 1 } } 45
Example 1 Contd… Manifest n n n n n <? xml version= "1. 0" encoding="utf-8"? > <manifest xmlns: android= "http: //schemas. android. com/apk/res/android" package= "cs 495. demos" android: version. Code= "1" android: version. Name= "1. 0"> <application android: icon= "@drawable/icon" android: label= "@string/app_name"> <activity android: name= ". Service. Driver 1" android: label= "@string/app_name"> <intent-filter> <action android: name= "android. intent. action. MAIN" /> <category android: name= "android. intent. category. LAUNCHER" /> </intent-filter> </activity> <service android: name= ". My. Service 1"> </service> </application> <uses-sdk android: min. Sdk. Version= "4" /> </manifest> 46
Example 1 Contd… Layout n n n n n <? xml version= "1. 0" encoding="utf-8"? > <Absolute. Layout android: id= "@+id/widget 32“ android: layout_width= "fill_parent“ android: layout_height= "fill_parent“ xmlns: android= "http: //schemas. android. com/apk/res/android" /> <Edit. Text android: id= "@+id/txt. Msg“ android: layout_width= "fill_parent“ android: layout_height= "120 px“ android: text. Size= "18 sp“ android: layout_x= "0 px“ android: layout_y= "57 px“ /> </Edit. Text> <Button android: id= "@+id/btn. Stop. Service“ android: layout_width= "151 px“ android: layout_height= "wrap_content“ android: text= " Stop Service“ android: layout_x= "43 px“ android: layout_y= "200 px" > </Button> </Absolute. Layout> 47
Example 1 Contd… Running n n n According to the Log 1. Main Activity is started (no displayed yet) 2. Service is started (on. Create, on. Start) 3. Main Activity UI is displayed 4. User stops Service 48
Example 2. Realistic Activity-Service Interaction n n n 1. The main activity starts the service and registers a receiver. 2. The service is slow, therefore it runs in a parallel thread its time consuming task. 3. When done with a computing cycle, the service adds a message to an intent. 4. The intents broadcasted using the filter: cs 495. action. DEMO 2 5. A Broadcast. Receiver (defined inside the main Activity) uses the previous filter and catches the message (displays the contents on the main UI ). 6. At some point the main activity stops the service and finishes executing. 49
Example 2 Contd… Layout <? xml version= "1. 0" encoding="utf-8"? > <Linear. Layout android: id= "@+id/widget 32" android: layout_width= "fill_parent" android: layout_height= "fill_parent" android: orientation= "vertical" xmlns: android="http: //schemas. android. com/apk/res/ android" > <Edit. Text android: id= "@+id/txt. Msg" android: layout_width= "fill_parent" android: layout_height= "120 px" android: text. Size= "12 sp" > </Edit. Text> <Button android: id= "@+id/btn. Stop. Service" android: layout_width= "151 px" android: layout_height= "wrap_content" android: text= "Stop Service" > </Button> </Linear. Layout> 50
Example 2 Contd… Manifest n n n n <? xml version= "1. 0" encoding="utf-8"? > <manifest xmlns: android= "http: //schemas. android. com/apk/res/android" package= "cis 493. demos“ android: version. Code= "1“ android: version. Name= "1. 0. 0"> <uses-sdkandroid: min. Sdk. Version= "4"></uses-sdk> <application android: icon= "@drawable/icon“ android: label="@string/app_name"> <activity android: name= ". My. Service. Driver“ android: label= "@string/app_name"> <intent-filter> <action android: name= "android. intent. action. MAIN" /> <category android: name= "android. intent. category. LAUNCHER" /> </intent-filter> </activity> <service android: name= "My. Service"> </service> </application> </manifest> 51
Example 2 Contd … Main Activity n n n n // Application logic and its Broadcast. Receiver in the same class package cs 495. demos; import java. util. Date; import android. app. Activity; import android. content. Broadcast. Receiver; import android. content. Component. Name; import android. content. Context; import android. content. Intent. Filter; import android. os. Bundle; import android. os. System. Clock; import android. util. Log; import android. view. View. On. Click. Listener; import android. widget. *; public class My. Service. Driver extends Activity { Text. View txt. Msg; Button btn. Stop. Service; Component Nameservice; Intent intent. My. Service; Broadcast. Receiver receiver; 52
Example 2 Contd… Main Activity n n n n @Override public void on. Create( Bundle saved. Instance. State){ super. on. Create(saved. Instance. State); set. Content. View(R. layout. main); txt. Msg= ( Text. View ) find. View. By. Id(R. id. txt. Msg); intent. My. Service= new Intent( this , My. Service. class); service= start. Service(intent. My. Service); txt. Msg. set. Text("My. Service started -(see DDMS Log)"); btn. Stop. Service= ( Button ) find. View. By. Id(R. id. btn. Stop. Service); btn. Stop. Service. set. On. Click. Listener( new On. Click. Listener() { public void on. Click( View v) { try { stop. Service( new Intent(intent. My. Service) ); txt. Msg. set. Text("After stoping. Service: n"+ service. get. Class. Name()); } catch (Exception e) { e. print. Stack. Trace(); } } }); 53
Example 2 Contd… Main Activity n n n n // register & define filter for local listener Intent. Filter main. Filter= new Intent. Filter("cs 495. action. DEMO 2"); receiver= new My. Main. Local. Receiver(); register. Receiver(receiver, main. Filter); // register } //on. Create @Override protected void on. Destroy() { super. on. Destroy(); try { stop. Service(intent. My. Service); // unregister. Receiver(receiver); } catch (Exception e) { Log. e("MAIN-DESTROY>>>", e. get. Message() ); } Log. e("MAIN-DESTROY>>>", "Adios"); } //on. Destroy 54
Example 2 Contd… Main Activity n n n n /////////////////////////////////// // local (embedded) RECEIVER public class My. Main. Local. Receiver extends Broadcast. Receiver{ @Override public void on. Receive( Context local. Context, Intent caller. Intent) { //Get data String service. Data= caller. Intent. get. String. Extra("service. Data"); Log. e("MAIN>>>", service. Data+ " -receiving data " + System. Clock. elapsed. Realtime() ); String now = "n"+ service. Data+ " ---“ + new Date(). to. Locale. String(); txt. Msg. append(now); } } //My. Main. Local. Receiver } //My. Service. Driver 55
Example 2 Contd… The Service n n n n n // Service uses a thread to run slow operation package cs 495. demos; import android. app. Service; import android. content. Intent; import android. os. IBinder; import android. util. Log; public class My. Service extends. Service { boolean is. Running= true; @Override public IBinder on. Bind( Intent arg 0) { return null ; } n n n @Override public void on. Create() { super. on. Create(); } 56
Example 2 Contd… The Service n n n n @Override public void on. Start( Intent intent, int start. Id) { super. on. Start(intent, start. Id); Log. e("<<My. Service-on. Start>>", "I am alive!"); // we place the slow work of the service in its own thread // so the caller is not hung up waiting for us Thread trigger. Service= new Thread ( new Runnable() { long starting. Time= System. current. Time. Millis(); long tics= 0; 57
Example 2 Contd… The Service n n n n public void run() { for ( int i=0; (i< 120) & is. Running; i++) { //at most 10 minutes try { //fake that you are very busy here tics= System. current. Time. Millis() -starting. Time; Intent my. Filtered. Response= new Intent(" "); //Set filter cs 495. action. DEMO 2 String msg= i+ " value: "+ tics; my. Filtered. Response. put. Extra("service. Data", msg); send. Broadcast(my. Filtered. Response); broadcasting Thread. sleep(1000); //five seconds } catch (Exception e) { e. print. Stack. Trace(); } } //for } //run }); trigger. Service. start(); } //on. Start 58
Example 2 Contd… The Service n n n n @Override public void on. Destroy() { super. on. Destroy(); Log. e("<<My. Service-on. Destroy>>", "I am dead"); is. Running= false; // Stop thread } //on. Destroy } //My. Service 59
References n App Development for Smart Devices n http: //www. cs. odu. edu/~cs 495/ 60
- Slides: 60