Android Services Mobile Application Development Selected Topics – CPIT 490 4-Oct-15.

60
Android Services Mobile Application Development Selected Topics – CPIT 490 Mar 22, 2 022

Transcript of Android Services Mobile Application Development Selected Topics – CPIT 490 4-Oct-15.

Android Services

Mobile Application Development

Selected Topics – CPIT 490

Apr 19, 2023

2

Objective

Working in Background Services BroadcastReceiver AsyncTask

3

Android Application Components

Activity Views Service Broadcast Receiver Content Provider Intents Widgets

4

Services 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 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 AndroidManifest.xml

<service android:name=”.MyService” /> To make service available to other applications

<service android:name=”.MyService”> <intent-filter> <action android:name=”net.learn2develop.MyService” /> </intent-filter> </service>

5

Services Services can be started with Context.startService() and

Context.bindService() in the main thread of the application’s process. CPU intensive tasks must be offloaded to background threads using

Thread or AsyncTask startService(new Intent(getBaseContext(), MyService.class)); startService(new Intent(“net.learn2develop.MyService”));

To stop a service: stopService(new Intent(getBaseContext(), MyService.class) or stopSelf()

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 public IBinder onBind(Intent arg0) { ... } public int onStartCommand(Intent intent, int flags, int startId) { ... } public void onDestroy() { ... }

6

Creating a Service Subclass Service, then override:

onStartCommand() -- called when startService() is called. Then you can call stopSelf() or stopService()

onBind() -- called when bindService() is called. Returns an IBinder (or null if you don't want to be bound).

onCreate() -- called before above methods. onDestroy() -- called when about to be shut down.

There are two classes you can subclass: Service: you need to create a new thread, since it is

not created by default. IntentService. This uses a worker thread to perform

the requests, and all you need to do is override onHandleIntent. This is the easiest, provided you don't need to handle multiple requests.

7

Services Lifecycle

A Service has three lifecycle methods: 1. void onCreate() 2. void onStartCommand() 3. void onDestroy()

onStartCommand() is invoked when a service is explicitly started using startService() method

onDestroy() is invoked when a service is stopped using stopService() method

8

Services Lifecycle To handle a block for code for specified time period, use Timer class within

the service private void doSomethingRepeatedly() { timer.scheduleAtFixedRate(new TimerTask() { public void run() { Log.d(“MyService”, String.valueOf(++counter));} }, 0, UPDATE_INTERVAL); }

You passed an instance of the TimerTask class to the scheduleAtFixedRate() method so that you can execute the block of code within the run() method repeatedly

The second parameter to the scheduleAtFixedRate() method specifies the amount of time, in milliseconds, before first execution

The third parameter specifies the amount of time, in milliseconds, between subsequent executions

TimerTask class itself implements Runnable interface and thus can be run on a separate thread. So, no need to wrap it in AsyncTask class

9

Creating a Serviceimport android.app.Service;

import android.content.Intent;

import android.os.IBinder;

public class MyService extends Service {

@Override

public void onCreate() {

// TODO: Actions to perform when service is created.

}

@Override

public IBinder onBind(Intent intent) {

// TODO: Replace with service binding implementation.

return null; }

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

// TODO Launch a background thread to do processing.

return Service.START_STICKY; }

@Override

public void onDestroy () {

// TODO: Actions to perform when service is ended.

} }

10

onStartCommand

Called whenever the Service is started with startService call So beware: may be executed several times in Service’s

lifetime! Controls how system will respond if Service restarted (START_STICKY) means the service will run indefinitely

until explicitly stopped Run from main GUI thread, so standard pattern is to create a

new Thread from onStartCommand to perform processing and stop Service when complete

11

Starting a Service

Call startService // Implicitly start a Service Intent myIntent = new Intent(MyService.ORDER_PIZZA) ; myIntent.putExtra("TOPPING", "Margherita"); startService(myIntent) ; // Explicitly start a Service startService(new Intent(this, MyService.class)) ; (To use this example, would need to include a ORDER_PIZZA

constant in MyService class and use an Intent Filter to register the Service as a provider of ORDER_PIZZA)

12

Stopping a Service

Call stopService ComponentName service = startService(new Intent(this,

BaseballWatch.class)) ;

// Stop a service using the service name. stopService(new Intent(this, service.getClass())); // Stop a service. // try { // Class serviceClass =

Class.forName(service.getClassName()); // stopService(new Intent(this, serviceClass)); // } catch (ClassNotFoundException e) {}

13

Passing Data b/w service & activity public void startService(View view) { Intent intent = new Intent(getBaseContext(), MyService.class); try { URL[] urls = new URL[] { new URL(“http://www.amazon.com/somefiles.pdf”), new URL(“http://www.wrox.com/somefiles.pdf”), intent.putExtra(“URLs”, urls); } catch (MalformedURLException e) { e.printStackTrace(); } startService(intent); } // use Bundle to pass data between activitiy and service public int onStartCommand(Intent intent, int flags, int startId) { // in service side Object[] objUrls = (Object[]) intent.getExtras().get(“URLs”); URL[] urls = new URL[objUrls.length]; // In Java, casting from one array type to another is not possible directly. Thus do for

each element for (int i=0; i<objUrls.length-1; i++) { urls[i] = (URL) objUrls[i]; } new DoBackgroundTask().execute(urls); return START_STICKY; }

14

Binding Activities to Services 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 onBind for the Service (in Service part) // create an instance of the MyBinder class   private final IBinder binder = new MyBinder(); // override the onBind() method to return the MyBinder instance @Override public IBinder onBind(Intent intent) { return binder; } // create an inner class that extends Binder class and implement

getService() method public class MyBinder extends Binder { MyService getService() { return MyService.this; } }

15

Binding Activities to Services

In onStartCommand() method (in service part) new DoBackgroundTask().execute(urls);

In Activity part Create instance of service and intent

MyService serviceBinder; Intent i;

Monitor the state of the service using an instance of ServiceConnection class

The onServiceConnected() method is called when the activity is connected to the service

The onServiceDisconnected()method is called when the service is disconnected from the activity.

16

Binding Activities to Services In onServiceConnected() method, get the instance of service using

getService() method and assign it to serviceBinder object Bind the activity to the service

public void startService(View view) { i = new Intent(ServicesActivity.this, MyService.class); bindService(i, connection, Context.BIND_AUTO_CREATE); }

bindService has three arguments: an Intent object, a ServiceConnection object, and a flag to indicate how the service should be bound

Start the service with startService(intentobject) using an intent object

Once Service is bound, all public methods and properties are available through the serviceBinder object obtained from the onServiceConnected handler

17

Binding Activities to Servicesprivate MyService serviceBinder; // Reference to the service

// Handles the connection between the service and activity

private ServiceConnection mConnection = new ServiceConnection() {

public void onServiceConnected(ComponentName className, IBinder service) {

// Called when the connection is made.

serviceBinder = ((MyService.MyBinder)service).getService();

}

public void onServiceDisconnected(ComponentName className) {

// Received when the service unexpectedly disconnects.

serviceBinder = null; }

};

@Override

public void onCreate(Bundle icicle) {

super.onCreate(icicle);

// Bind to the service

Intent bindIntent = new Intent(MyActivity.this, MyService.class) ;

bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);

}

18

Services Declare services in manifest Service Lifecycle:

onCreate, onStartCommand, onDestroy Can start services by passing in an intent similar to starting an

activity Must stop service before starting up another instance

Best to start service in onCreate/onResume and stop in onPause

19

Background threads To make application responsive, move all time-consuming

operations off main app thread to child thread. Very important! Two options:

AsyncTask Create an inner class that extends AsyncTask class. The AsyncTask

class enables handling of background execution without manually handling threads and handlers

private class abc extends AsyncTask<URL, Integer, Long> { The inner class has three methods: doInBackground() 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; onProgressUpdate() accepts an array of 2nd generic type (Integer in this case) as parameter; onPostExecute() accepts 3rd generic type (Long in this case) as parameter

Write own Threads

20

AsyncTask<Params, Progress, Result>

Execution of asynchronous task goes through following main steps: doInBackground(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 onPostExecute(). publishProgress(Progress...), which is invoked from doInBackground(), is used to publish one or more units of progress by calling onProgressUpdate(Progress...).

onProgressUpdate(Progress...): invoked after a call to publishProgress(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.

onPostExecute(Result): invoked after the background computation finishes. The result of the background computation is passed to this step as a parameter.

21

AsyncTask<Params, Progress, Result>

Pressing the back button in the emulator or device will close the activity but the task will keep on running

To stop the AsyncTask subclass, you need to get an instance of it first. To stop the task, call its cancel() method. Within the task, you call the isCancelled() method to check whether the task should be terminated

public class ThreadingActivity extends Activity { static TextView txtView1; DoCountingTask task; public void stopCounter(View view) { task.cancel(true); } private class DoCountingTask extends AsyncTask<Void, Integer, Void> { protected Void doInBackground(Void... params) { publishProgress(i); … if (isCancelled()) break; } return null; } protected void onProgressUpdate(Integer... progress) { … } } protected void onPause() { super.onPause(); stopCounter(txtView1); }

22

Creating AsyncTask new DownloadFilesTask().execute(url1, url2, url3); //this call in onStartCommand() private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { @Override protected Long doInBackground(URL... urls) { //Background thread. Do not interact with UI int myProgress = 0; long result=0; // [... Perform background processing task, update myProgress ...] PublishProgress(myProgress) // [... Continue performing background processing task ...] // Return the value to be passed to onPostExecute return result; } @Override protected void onProgressUpdate(Integer... progress) { //Post interim updates to UI thread; access UI // [... Update progress bar, Notification, or other UI element ...] } @Override protected void onPostExecute(Long result) { //Run when doInBackground completed; access UI // [... Report results via UI update, Dialog, or notification ...] showDialog("Downloaded " + result + " bytes"); } }

23

Services using IntentService class

To easily create a service that runs a task asynchronously and terminates itself when it is done, you can use the IntentService class

The IntentService 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 IntentService class instead of Service class public class MyIntentService extends IntentService { } // create a constructor and call superclass with the name of the intent service as

a string public MyIntentService() { super(“MyIntentServiceName”); } // onHandleIntent() is executed on a worker thread protected void onHandleIntent(Intent intent) { … }

24

Services using IntentService class

The IntentService class does the following: Creates a default worker thread that executes all intents delivered to

onStartCommand() separate from your application's main thread. Creates a work queue that passes one intent at a time to your onHandleIntent()

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 stopSelf(). Provides default implementation of onBind() that returns null. Provides a default implementation of onStartCommand() that sends the intent

to the work queue and then to your onHandleIntent() implementation.

All you have to do is handle onHandleIntent().

25

Services using IntentService class

public class HelloIntentService extends IntentService { // A constructor is required, and must call the super IntentService(String) // constructor with a name for the worker thread. public HelloIntentService() { super("HelloIntentService"); } // The IntentService calls this method from the default worker thread with the intent that started // the service. When this method returns, IntentService stops the service, as appropriate. @Override protected void onHandleIntent(Intent intent) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. long endTime = System.currentTimeMillis() + 5*1000; while (System.currentTimeMillis() < endTime) { synchronized (this) { try { wait(endTime - System.currentTimeMillis()); } catch (Exception e) { } }}}}

26

Running a Service in Foreground

To request running in foreground: startForeground() To remove from foreground: stopForeground()

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), System.currentTimeMillis());

Intent notificationIntent = new Intent(this, ExampleActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,

notificationIntent, 0);notification.setLatestEventInfo(this, getText(R.string.notification_title), getText(R.string.notification_message), pendingIntent);startForeground(ONGOING_NOTIFICATION, notification);

27

Creating own threads // 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++) { txtView1.setText(String.valueOf(i)); } //

WRONG // update using post method of any view with Runnable //---update UI like this --- txtView1.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

28

Creating own threads 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 handleMessage(Message msg) { byte[] buffer = (byte[]) msg.obj; //---convert the entire byte array to string--- String strReceived = new String(buffer); //-display the text received on the TextView--- txtView1.setText(strReceived); public void startCounter(View view) { new Thread(new Runnable() { @Override public void run() { //---update the main activity UI--- ThreadingActivity.UIupdater.obtainMessage(0,

String.valueOf(i).getBytes() ).sendToTarget(); Refer: http://developer.android.com/reference/android/os/Handler.html

29

BroadcastReceiver

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.

30

BroadcastReceiver

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. Important: you must complete tasks in a BroadcastReceiver

within <10s. If you have a task that will take longer, you must start a new thread to avoid application assassin OS.

31

BroadcastReceiver Lifecycle The system delivers a broadcast Intent to all interested broadcast

receivers, which handle the Intent sequentially.

32

BroadcastReceiver Lifecycle

A broadcast receiver has a single callback method: void onReceive(Context curContext, Intent broadcastMsg) 1. When a broadcast message arrives to a receiver, Android calls

its onReceive() 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 onReceive() returns, it is inactive.

33

Example

• Starting Broadcast

public static final String NEW_LIFEFORM_DETECTED =

“com.paad.action.NEW_LIFEFORM”;

Intent intent = new Intent(NEW_LIFEFORM_DETECTED);

intent.putExtra(“lifeformName”, lifeformType);

sendBroadcast(intent);

• BroadcastReceiver

import android.content.BroadcastReceiver;

import android.content.Intent;

import android.content.Context;

public class MyBroadcastReceiver extends BroadcastReceiver {

@Override

public void onReceive( Context context, Intent intent) {

//TODO: React to the Intent received.

}

}

34

Example 2 Starting Broadcast //---send a broadcast to inform the activity Intent broadcastIntent = new Intent(); broadcastIntent.setAction(“FILE_DOWNLOADED_ACTION”); // only those

activities listening for this intent will be invoked getBaseContext().sendBroadcast(broadcastIntent); BroadcastReceiver public void onResume() { super.onResume(); //---intent to filter for file downloaded intent--- intentFilter = new IntentFilter();

intentFilter.addAction(“FILE_DOWNLOADED_ACTION”); //---register the receiver--- registerReceiver(intentReceiver, intentFilter); } private BroadcastReceiver intentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { … } };

35

Manifest

The manifest of applications using Android Services must include: If the application defines a BroadcastReceiver 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.

36

Manifest <?xml version = "1.0" encoding = "utf-8" ?> <manifest xmlns:android = "http://schemas.android.com/apk/res/android" package = "cs495.demos" android:versionCode = "1“ android:versionName = "1.0.0" > <uses-sdk android:minSdkVersion = "4" ></uses-sdk> <application android:icon = "@drawable/icon" android:label = "@string/app_name" > <activity android:name = ".MyServiceDriver2“ > <intent-filter> <action android:name = "android.intent.action.MAIN" /> <category android:name = "android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name = “.MyService2" /> <receiver android:name = “.MyBroadcastReceiver" > <intent-filter> <action android:name = "com.paad.action.NEW_LIFEFORM" /> </intent-filter> </receiver> </application> </manifest>

37

Native Broadcasts 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/

Intent.html

38

Device Power

Just because you have code in a BroadcastReceiver 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 WakeLock!

39

WakeLock

Control the power state on device (somewhat) Used to

Keep the CPU running Prevent screen dimming or going off Prevent backlight from turning on

Only use when necessary and release as quickly as possible Need to request the

android.permission.WAKE_LOCK permission in the <uses-permission> element of the manifest file.

40

Creating a WakeLock PowerManager pm =

(PowerManager)getSystemService(Context.POWER_SERVICE); WakeLock wakeLock =

pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock"); wakeLock.acquire(); [ ... Do things requiring the CPU stay active ... ] wakeLock.release(); PARTIAL_WAKE_LOCK keeps the CPU running without the screen on

41

Project Ideas

Security ODU Secure Application

Localization 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

Parkin's disease detection EEG Set

Transportation Detecting and identifying whether group of people are on the

same transport unit using correlation of accelerometer, gyro, etc

42

Project Ideas

Education Engineering management game

Misc Understanding Interface activities power consumption Extension of MagnoTricoder Bird Sound Detection

  Last Year Projects:

http://www.cs.odu.edu/~nadeem/classes/cs495-F11/projects.htm

43

Example 1. A very Simple Service The main application starts a service. The service prints lines on the DDMS

LogCat until the main activity stops the service. // a simple service is started & stopped package cs495.demos; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.*; public class ServiceDriver1 extends Activity { TextView txtMsg; Button btnStopService; ComponentName service; Intent intentMyService;

44

Example 1 Contd… @Override public void onCreate( Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout. main); txtMsg= ( TextView ) findViewById(R.id. txtMsg); intentMyService = new Intent(this, MyService1.class); service = startService(intentMyService); btnStopService= ( Button ) findViewById(R.id. btnStopService); btnStopService.setOnClickListener( new OnClickListener() { public void onClick( View v) { try { stopService((intentMyService)); txtMsg.setText("After stopingService: \n" + service.getClassName()); } catch (Exception e) { Toast. makeText(getApplicationContext(), e.getMessage(), 1).show(); } } } ); } }

45

Example 1 Contd… Service //non CPU intensive service running the main task in its main thread package cs495.demos; Import android.app.Service; Import android.content.Intent; Import android.os.IBinder; Import android.util.Log; public class MyService1 extends Service { @Override public IBinderonBind(Intent arg0) { return null ; } @Override public void onCreate() { super .onCreate(); Log. i("<<MyService1-onStart>>", "I am alive-1!"); } @Override public void onStart(Intent intent, intstartId) { super .onStart(intent, startId); Log. i("<<MyService1-onStart>>", "I did something very quickly"); } @Override public void onDestroy() { super.onDestroy(); Log. i("<<MyService1-onDestroy>>", "I am dead-1"); } }//MyService1

46

Example 1 Contd… Manifest <?xml version= "1.0" encoding="utf-8"?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= "cs495.demos" android:versionCode= "1" android:versionName= "1.0"> <application android:icon= "@drawable/icon" android:label= "@string/app_name"> <activity android:name= ".ServiceDriver1" 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= ".MyService1"> </service> </application> <uses-sdk android:minSdkVersion= "4" /> </manifest>

47

Example 1 Contd… Layout <?xml version= "1.0" encoding="utf-8"?> <AbsoluteLayout android:id= "@+id/widget32“ android:layout_width= "fill_parent“ android:layout_height= "fill_parent“ xmlns:android= "http://schemas.android.com/apk/res/android" /> <EditText android:id= "@+id/txtMsg“ android:layout_width= "fill_parent“ android:layout_height= "120px“ android:textSize= "18sp“ android:layout_x= "0px“ android:layout_y= "57px“ / > </EditText> <Button android:id= "@+id/btnStopService“ android:layout_width= "151px“ android:layout_height= "wrap_content“ android:text= " Stop Service“ android:layout_x= "43px“ android:layout_y= "200px" > </Button> </AbsoluteLayout>

48

Example 1 Contd… Running

According to the Log 1. Main Activity is started (no displayed yet) 2. Service is started (onCreate, onStart) 3. Main Activity UI is displayed 4. User stops Service

49

Example 2. Realistic Activity-Service Interaction

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: cs495.action.DEMO2 5. A BroadcastReceiver (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.

50

Example 2 Contd… Layout<?xml version= "1.0" encoding="utf-8"?>

<LinearLayout

android:id= "@+id/widget32" android:layout_width= "fill_parent"

android:layout_height= "fill_parent" android:orientation= "vertical" xmlns:android="http://schemas.android.com/apk/res/android" >

<EditText android:id= "@+id/txtMsg" android:layout_width= "fill_parent"

android:layout_height= "120px" android:textSize= "12sp" >

</EditText>

<Button android:id= "@+id/btnStopService" android:layout_width= "151px"

android:layout_height= "wrap_content" android:text= "Stop Service"

> </Button> </LinearLayout>

51

Example 2 Contd… Manifest <?xml version= "1.0" encoding="utf-8"?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= "cis493.demos“ android:versionCode= "1“ android:versionName= "1.0.0"> <uses-sdkandroid:minSdkVersion= "4"></uses-sdk> <application android:icon= "@drawable/icon“ android:label="@string/app_name"> <activity android:name= ".MyServiceDriver“ 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= "MyService"> </service> </application> </manifest>

52

Example 2 Contd … Main Activity // Application logic and its BroadcastReceiver in the same class package cs495.demos; import java.util.Date; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.*; public class MyServiceDriver extends Activity { TextView txtMsg; Button btnStopService; Component Nameservice; Intent intentMyService; BroadcastReceiver receiver;

53

Example 2 Contd… Main Activity @Override public void onCreate( Bundle savedInstanceState){ super. onCreate(savedInstanceState); setContentView(R.layout. main); txtMsg= ( TextView ) findViewById(R.id. txtMsg); intentMyService= new Intent( this , MyService.class); service= startService(intentMyService); txtMsg.setText("MyService started -(see DDMS Log)"); btnStopService= ( Button ) findViewById(R.id. btnStopService); btnStopService.setOnClickListener( new OnClickListener() { public void onClick( View v) { try { stopService( new Intent(intentMyService) ); txtMsg.setText("After stopingService: \n"+ service.getClassName()); } catch (Exception e) { e.printStackTrace(); } } });

54

Example 2 Contd… Main Activity // register & define filter for local listener IntentFilter mainFilter= new IntentFilter("cs495.action.DEMO2"); receiver= new MyMainLocalReceiver(); registerReceiver(receiver, mainFilter); // register } //onCreate @Override protected void onDestroy() { super .onDestroy(); try { stopService(intentMyService); // unregister unregisterReceiver(receiver); } catch (Exception e) { Log. e("MAIN-DESTROY>>>", e.getMessage() ); } Log. e("MAIN-DESTROY>>>", "Adios"); } //onDestroy

55

Example 2 Contd… Main Activity ////////////////////////////////////////////////////////////////////// // local (embedded) RECEIVER public class MyMainLocalReceiver extends BroadcastReceiver{ @Override public void onReceive( Context localContext, Intent callerIntent) { //Get data String serviceData= callerIntent.getStringExtra("serviceData"); Log. e("MAIN>>>", serviceData+ " -receiving data " + SystemClock. elapsedRealtime() ); String now = "\n"+ serviceData+ " ---“ + new Date().toLocaleString(); txtMsg.append(now); } } //MyMainLocalReceiver } //MyServiceDriver

56

Example 2 Contd… The Service // Service uses a thread to run slow operation package cs495.demos; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MyService extendsService { boolean isRunning= true; @Override public IBinder onBind( Intent arg0) { return null ; } @Override public void onCreate() { super .onCreate(); }

57

Example 2 Contd… The Service @Override public void onStart( Intent intent, int startId) { super .onStart(intent, startId); Log. e("<<MyService-onStart>>", "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 triggerService= new Thread ( new Runnable() { long startingTime= System. currentTimeMillis(); long tics= 0;

58

Example 2 Contd… The Service public void run() { for ( int i=0; (i< 120) & isRunning; i++) { //at most 10 minutes try { //fake that you are very busy here tics= System. currentTimeMillis() -startingTime; Intent myFilteredResponse= new Intent(" "); //Set filter cs495.action.DEMO2 String msg= i+ " value: "+ tics; myFilteredResponse.putExtra("serviceData", msg); sendBroadcast(myFilteredResponse); broadcasting Thread. sleep(1000); //five seconds } catch (Exception e) { e.printStackTrace(); } } //for } //run }); triggerService.start(); } //onStart

59

Example 2 Contd… The Service

@Override public void onDestroy() { super .onDestroy(); Log. e("<<MyService-onDestroy>>", "I am dead"); isRunning= false; // Stop thread } //onDestroy } //MyService

60

References

App Development for Smart Devices http://www.cs.odu.edu/~cs495/