Transcript service
Android Services
Mobile Application Development
Selected Topics – CPIT 490
2-Apr-16
Objective
Working in Background
Services
BroadcastReceiver
AsyncTask
2
Android Application Components
Activity
Views
Service
Broadcast Receiver
Content Provider
Intents
Widgets
3
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>
4
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() { ... }
5
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.
6
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
7
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
8
Creating a Service
import 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.
} }
9
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
10
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)
11
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) {}
12
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; }
13
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; }
}
14
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.
15
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
16
Binding Activities to Services
private 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);
}
17
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
18
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
19
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.
20
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); }
21
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");
} }
22
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) { … }
23
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().
24
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) { }
}}}}
25
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);
26
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
27
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
28
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.
29
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.
30
BroadcastReceiver Lifecycle
The system delivers a broadcast Intent to all interested broadcast
receivers, which handle the Intent sequentially.
31
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.
32
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.
}
}
33
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) { … } };
34
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.
35
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>
36
</application> </manifest>
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/Int
ent.html
37
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!
38
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 <usespermission> element of the manifest file.
39
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
40
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
41
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/cs495F11/projects.htm
42
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;
43
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();
}
}
} );
} }
44
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
45
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>
46
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>
47
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
48
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.
49
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>
50
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>
51
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;
52
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(); } } });
53
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
54
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
55
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(); }
56
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;
57
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
58
Example 2 Contd… The Service
@Override
public void onDestroy() {
super .onDestroy();
Log. e("<<MyService-onDestroy>>", "I am dead");
isRunning= false;
// Stop thread
} //onDestroy
} //MyService
59
References
App Development for Smart Devices
http://www.cs.odu.edu/~cs495/
60