mobile programming lecture 8

Post on 24-Feb-2016

47 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Mobile Programming Lecture 8. Notifications, Services, AsyncTask. Lecture 7 Review. How and where in your code do you distinguish between multiple Dialogs in an Activity? How and where in your code do you determine which Menu Option was clicked? - PowerPoint PPT Presentation

TRANSCRIPT

Mobile Programming Lecture 8

Notifications, Services, AsyncTask

• How and where in your code do you distinguish

between multiple Dialogs in an Activity?

• How and where in your code do you determine

which Menu Option was clicked?

• After creating an Options Menu, can you use

the same XML file to create a Context Menu?

Lecture 7 Review

• How can you edit SharedPreferences?

• What's the difference between calling

o getSharedPreferences(String, int) and

o getDefaultSharedPreferences(Context);

• How can you tell when Preferences have been changed

at runtime?

Lecture 7 Review

Agenda

• NotificationManager

• Notification

• PendingIntent

• Service

• Communicating with Service

• MediaPlayer

• AsyncTask

Notifications

• Notifications give you the ability to let the user know directly about what work has been completed

• �Send a notification that the file has started downloading

• After the file completes the service can send out a notification saying that the file has been downloaded successfully.

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Although Notifications are usually sent from Services, we send it from an Activity since that's what you know at this point

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

This will be used as an identifier for this notification unique within this application.

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

You must use the NotificationManager if you want to send a Notification

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher, "Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Let's create a new Notification

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

First argument is an icon which should be in res/drawable. I reused the launcher icon here because I'm lazy

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

This is the message that pops up in the status bar when the Notification is delivered. The user doesn't see this message again after that

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

This is the time that will be shown in the Notification, not the time that the Notification will be delivered.

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Let's set up an Intent for launching a new Activity

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Since we don't control the NotificationManager, we need to supply it with our Intent so that it can act on our behalf

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

In this case, we want it to launch our second Activity, so we provide it with an Intent that does just that

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Let's add information for our Notification

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

We need the Context of our application

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

A Title that the user will see in the Notification until it dissappears

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

A message that appears below the Title

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Our PendingIntent to be launched when the Notification is clicked

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR; mNotificationManager.notify(NOTIFICATION_ID, notification);

}

You can add flags to your Notification. Use | to add multiple flags

Notificationspublic class NotificationExample extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final int NOTIFICATION_ID = 1;

NotificationManager mNotificationManager =

(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Notification notification = new Notification(R.drawable.ic_launcher,

"Hi There", System.currentTimeMillis());

Intent notificationIntent = new Intent(this, SecondActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(this, "You have been notified",

"Click to launch second Activity", contentIntent);

notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_NO_CLEAR;

mNotificationManager.notify(NOTIFICATION_ID, notification);

}

Notify the user! You need to supply an id (int) unique within this application, and the Notification itself

Notifications

• See NotificationExample.tar

• Note that this way of doing it is deprecated

• Android 3.0 and higher can still use it, but should use Notification.Builder instead• http://developer.android.com/training/notify-user/build

-notification.html

Android Application Components

1. Activity

2. Broadcast Receiver

3. Content Provider

4. Service

Service - What is it?

• a Service is an application component representing an application's desire to o perform a longer-running operation while not

interacting with the usero supply functionality for other applications to use

• a Service is a facility for the application too tell the system about something it wants to be doing

in the background o expose some of its functionality to other applications

Service - What is it NOT?

• �a Service is not a separate process.o it does not imply it is running in its own process o it runs in the same process as the application it is in

unless otherwise specified

• �a Service is not a thread

• it is not a means itself to do work off the main thread

Service - Why use Services?• �For functions that do not require access to an activity’s UI

o Performing operations that need to continue even after the application’s activities are not visible �Long Downloads (Android Market) �Playing Music (Pandora)

• �Performing operations that need to exist regardless of activities coming and goingo �Maintaining a connection for a chat application

• �Performing periodic work without user intervention.o �Updating the Weather Widget.

Service - Process LifeCycle

Android will attempt to keep the process hosting a service around as long as the service has been started or has clients bound to it

• If the service is currently executing code in its onCreate(), onStartCommand(), or onDestroy() methods, then the hosting process will be a foreground process to ensure this code can execute without being killed.

Service - Forms of a ServiceA service can take 2 forms

• A Started Service is one where an application component (such as an Activity) starts it by calling startService()o it can then run in the background indefinitely, even if the component that

started it has been destroyedo onStartCommand() allows it to start

• A Bound Service is one where an application component binds to it by calling bindService()o it then offers a client-server interface that allows components to interact with ito a bound service runs only as long as an another application component is

bound to ito multiple component can bind to the service at the same timeo onBind() allows binding on the Service

Service - LifeCycle

This is important

Service - LifeCyclein either case ...

• onCreate()o not called if Service is already running

• onStartCommand()o service now started and can run in background indefinitely

• onDestroy()o Service is no longer in use and is being destroyed

Adding a Service to your Project

• Open AndroidManifest.xml• Click on the Application Tab• Under Application Nodes, click Add ...• Select Service• Under Attributes for Service, click on Name*• Enter the name of your Service, e.g.

MyService• Your class may be underlined in red, mouse

over it and choose Add unimplemented methods

Creating a Started Service

Override the Service method:

public int onStartCommand(Intent, int, int)

• to stop the Service (you should when it's job is done)o the Service should stop itself by calling stopSelf() when it's job is

done

• another component can call stopService(Intent)

Creating a Started Servicepublic class MyActivity extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

myIntent = new Intent(this, MyService.class);startService(myIntent);

}}

Creating a Started Servicepublic class MyActivity extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

myIntent = new Intent(this, MyService.class);startService(myIntent);

}}

Here we start with an Activity

Creating a Started Servicepublic class MyActivity extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

myIntent = new Intent(this, MyService.class);startService(myIntent);

}}

Looks familiar? Starting a Service is almost the same as starting an Activity

Creating a Started Servicepublic class MyActivity extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

myIntent = new Intent(this, MyService.class);startService(myIntent);

}}

We call startService() instead of startActivity() thoguh

Creating a Started Servicepublic class MyService extends Service {

@Override

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

Log.i(TAG, "Service.onStartCommand()");

final int LIMIT = 10;

int i;

// do nothing for LIMIT iterations

for(i = 0; i < LIMIT; i++) ;

stopSelf();

return Service.START_STICKY;

}

}

Here we extend Service

Creating a Started Servicepublic class MyService extends Service {

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

Log.i(TAG, "Service.onStartCommand()");

final int LIMIT = 10;

int i;

// do nothing for LIMIT iterations

for(i = 0; i < LIMIT; i++) ;

stopSelf();

return Service.START_STICKY;

}

}

We override onStartCommand(), which is called each time startService() is called

Creating a Started Servicepublic class MyService extends Service {

@Override

public int onStartCommand(Intent intent, int flags, int startId) {Log.i(TAG, "Service.onStartCommand()");

final int LIMIT = 10;

int i;

// do nothing for LIMIT iterations

for(i = 0; i < LIMIT; i++) ;

stopSelf();

return Service.START_STICKY;

}

}

Note the semicolon. This for loop is empty and is just there to simulate the Service doing some work

Creating a Started Servicepublic class MyService extends Service {

@Override

public int onStartCommand(Intent intent, int flags, int startId) {Log.i(TAG, "Service.onStartCommand()");

final int LIMIT = 10;

int i;

// do nothing for LIMIT iterations

for(i = 0; i < LIMIT; i++) ;

stopSelf();

return Service.START_STICKY;

}

}

The Service is done so it stops itself

Creating a Started Servicepublic class MyService extends Service {

@Override

public int onStartCommand(Intent intent, int flags, int startId) {Log.i(TAG, "Service.onStartCommand()");

final int LIMIT = 10;

int i;

// do nothing for LIMIT iterations

for(i = 0; i < LIMIT; i++) ;

stopSelf();

return Service.START_STICKY;}

}

onStartCommand() must return a value, although this return value may be useless here since we called stopSelf()

Creating a Started Service

See ServiceLifeCycleExample.tar

Creating a Started ServiceonStartCommand() return values

• START_STICKYo if this service's process is killed while it is started (after returning from

onStartCommand() ), then leave it in the started state.o This is suitable for media players (or similar services) that are not

executing commands, but running indefinitely and waiting for a job

• START_NOT_STICKYo if this service's process is killed while it is started, then take the

service out of the started state and don't recreate.

• START_REDELIVER_INTENTo if this service's process is killed while it is started (after returning from

onStartCommand()), then it will be scheduled for a restart and the last delivered Intent re-delivered to it

Creating a Started Service

To create a started service, you can either extend Service or IntentService

• Serviceo it uses your main application's thread by default and

can slow down your app you should create a new thread for the Service to

work in if it slows down your app

• IntentServiceo ...

IntentService

If you don't want to create a separate thread yourself, you can extend IntentService, which

•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.

IntentService

In other words

• You really only need a o constructoro to override onHandleIntent(Intent)

If you decide to override onCreate() or onStartCommand() or onDestroy() anyway, then you should call super.on_()

IntentServicepublic class MyService extends IntentService {

private static final String TAG = "ServiceExample";

public MyService() {super("MyService");

}

@Overrideprotected void onHandleIntent(Intent intent) {

final int LIMIT = 200000000;int i;

for(i = 0; i < LIMIT; i++) ;}

}

Communicating with a Service

• Typically you would like to tell the application about events that occurs inside a service.

• The service client (e.g. Activity) can provide some sort of “callback” or “listener” object to the service, which the service could then call when needed.

Communicating with a Service

Here are several ways that you can have your client communicate with your Service

1. Broadcast Intent2. Pending Result3. Messenger

Communicating with a Service - 1. Broadcast Intent

1. BroadcastIntent Example

This code example involves these components

• Activity

• Service

• BroadcastReceiver

Communicating with a Service - 1. Broadcast Intent

public class MyActivity extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent sIntent = new Intent(getApplicationContext(), MyService.class);sIntent.putExtra("myaction", "loop");startService(sIntent);

}});

}}

Here we start with an Activity

Communicating with a Service - 1. Broadcast Intent

public class MyActivity extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent sIntent = new Intent(getApplicationContext(), MyService.class);sIntent.putExtra("myaction", "loop");startService(sIntent);

}});

}}

Add some extra information to the Intent so that the Service can know which job to perform

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

Here we extend IntentService instead of Service

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

In doing so, you must have a constructor

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

and we override onHandleIntent() instead of onStartCommand()

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

Get the extras out of the intent, and let's see if we're tasked to loop

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

If so, then let's do some work!

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

This is just an example of how to send a task to a Service. You can do this with by extending Service as well as IntentService

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

Let's intend on making an explicit broadcast

Communicating with a Service - 1. Broadcast Intent

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 1000000000;Bundle extras = intent.getExtras();

if(extras != null){

if(extras.getString("myaction").equals("loop"))for(i = 0; i < LIMIT; i++);

}

Intent myIntent = new Intent(this, MyReceiver.class);sendBroadcast(myIntent);

}}

Send the broadcast and ...

Communicating with a Service - 1. Broadcast Intent

public class MyReceiver extends BroadcastReceiver {

@Overridepublic void onReceive(Context context, Intent intent) {

Toast.makeText(context,

"Broadcast Received, Work Completed",Toast.LENGTH_LONG)

.show();}

}

Voila! We had a BroadcastReceiver set up already of course

Communicating with a Service - 1. Broadcast Intent

public class MyReceiver extends BroadcastReceiver {

@Overridepublic void onReceive(Context context, Intent intent) {

Toast.makeText(context,

"Broadcast Received, Work Completed",Toast.LENGTH_LONG)

.show();}

}

In here we can take whatever action we want to.

Communicating with a Service - 1. Broadcast Intent

public class MyReceiver extends BroadcastReceiver {

@Overridepublic void onReceive(Context context, Intent intent) {

Toast.makeText(context,

"Broadcast Received, Work Completed",Toast.LENGTH_LONG)

.show();}

}

The Service could have added extras to the Intent to give us more information

Communicating with a Service - 1. Broadcast Intent

public class MyReceiver extends BroadcastReceiver {

@Overridepublic void onReceive(Context context, Intent intent) {

Toast.makeText(context,

"Broadcast Received, Work Completed",Toast.LENGTH_LONG)

.show();}

}

Depending on that, we may want to take some action such as give a Notification

Communicating with a Service - 1. Broadcast Intent

public class MyReceiver extends BroadcastReceiver {

@Overridepublic void onReceive(Context context, Intent intent) {

Toast.makeText(context,

"Broadcast Received, Work Completed",Toast.LENGTH_LONG)

.show();}

}Or do nothing at all

Communicating with a Service - 1. Broadcast Intent

See ServiceBroadcastIntent.tar

Communicating with a Service - 2. Pending Result

2. PendingResult Example

This code example involves the following components

• Activity• Service

Communicating with a Service - 2. Pending Result

Remember, the reason for a PendingIntent is to allow a different app to fulfill an Intent on our behalf

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

PendingIntent contentIntent = createPendingResult(15, new Intent(), 0); final Intent sIntent = new Intent(this, MyService.class);sIntent.putExtra("pending",contentIntent);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Override public void onClick(View v) {startService(sIntent);

}});

}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {...

}}

Starting with our Activity

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

PendingIntent contentIntent = createPendingResult(15, new Intent(), 0); final Intent sIntent = new Intent(this, MyService.class);sIntent.putExtra("pending",contentIntent);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Override public void onClick(View v) {startService(sIntent);

}});

}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {...

}}

We call Activity.createPendingResult, which returns a PendingIntent

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

PendingIntent contentIntent = createPendingResult(15, new Intent(), 0); final Intent sIntent = new Intent(this, MyService.class);sIntent.putExtra("pending",contentIntent);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Override public void onClick(View v) {startService(sIntent);

}});

}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {...

}}

When the result is returned out our Activity, we want to identify our task using the number 15 (any number you to distinguish between results)

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

PendingIntent contentIntent = createPendingResult(15, new Intent(), 0); final Intent sIntent = new Intent(this, MyService.class);sIntent.putExtra("pending",contentIntent);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Override public void onClick(View v) {startService(sIntent);

}});

}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {...

}}

We create an Intent that can start a Service

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

PendingIntent contentIntent = createPendingResult(15, new Intent(), 0); final Intent sIntent = new Intent(this, MyService.class);sIntent.putExtra("pending",contentIntent);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Override public void onClick(View v) {startService(sIntent);

}});

}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {...

}}

We package our PendingIntent inside of our Service Intent, so that the Service can use it on our behalf

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

PendingIntent contentIntent = createPendingResult(15, new Intent(), 0); final Intent sIntent = new Intent(this, MyService.class);sIntent.putExtra("pending",contentIntent);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Override public void onClick(View v) {startService(sIntent);

}});

}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {...

}}

Let's go ahead and start the Service whenever a Button is clicked

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);

PendingIntent contentIntent = createPendingResult(15, new Intent(), 0); final Intent sIntent = new Intent(this, MyService.class);sIntent.putExtra("pending",contentIntent);

Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Override public void onClick(View v) {startService(sIntent);

}});

}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

... }

}

We will get back to this method soon shortly

Communicating with a Service - 2. Pending Result

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 500000000;

for(i = 0; i < LIMIT; i++);

PendingIntent pIntent = (PendingIntent) intent.getParcelableExtra("pending");

try {pIntent.send(1);

} catch (CanceledException e) {e.printStackTrace();

}}

}

Here's our Service!

Communicating with a Service - 2. Pending Result

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 500000000;

for(i = 0; i < LIMIT; i++);

PendingIntent pIntent = (PendingIntent) intent.getParcelableExtra("pending");

try {pIntent.send(1);

} catch (CanceledException e) {e.printStackTrace();

}}

}

This get's called because the Button in the Activity was clicked, which then called startService()

Communicating with a Service - 2. Pending Result

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 500000000;

for(i = 0; i < LIMIT; i++);

PendingIntent pIntent = (PendingIntent) intent.getParcelableExtra("pending");

try {pIntent.send(1);

} catch (CanceledException e) {e.printStackTrace();

}}

}

Remember the PendingIntent that was packaged? Let's get it!

Communicating with a Service - 2. Pending Result

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 500000000;

for(i = 0; i < LIMIT; i++);

PendingIntent pIntent = (PendingIntent) intent.getParcelableExtra("pending");

try {pIntent.send(1);

} catch (CanceledException e) {e.printStackTrace();

}}

}

Let's try sending a result (1 in this case) back to the Activity

Communicating with a Service - 2. Pending Result

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 500000000;

for(i = 0; i < LIMIT; i++);

PendingIntent pIntent = (PendingIntent) intent.getParcelableExtra("pending");

try {pIntent.send(1);

} catch (CanceledException e) {e.printStackTrace();

}}

}

This works because this PendingIntent was created in our Activity using createPendingResult()

Communicating with a Service - 2. Pending Result

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {

int i;int LIMIT = 500000000;

for(i = 0; i < LIMIT; i++);

PendingIntent pIntent = (PendingIntent) intent.getParcelableExtra("pending");

try {pIntent.send(1);

} catch (CanceledException e) {e.printStackTrace();

}}

}

So where does the code go from here (if there are no Exceptions of course)

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD", Toast.LENGTH_SHORT).show()

}}

}

Voila, back to our Activity, Activity.onActivityResult() specifically

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD", Toast.LENGTH_SHORT).show()

}}

}

This is a callback method, which means that the system calls this method if you have it define

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD", Toast.LENGTH_SHORT).show()

}}

}

See it here

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD", Toast.LENGTH_SHORT).show()

}}

}

requestCode should already be set to 15, because that's the number we passed as argument to createPendingResult()

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD", Toast.LENGTH_SHORT).show()

}}

}

resultCode should already be set to 1, because the Service set this value using PendingIntent.send()

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD", Toast.LENGTH_SHORT).show()

}}

}

The Service could have possible added extra information to the Intent that was provided in Service.onHandleIntent (although we didn't do so in this example)

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD", Toast.LENGTH_SHORT).show()

}}

}

Let's make sure that this is our request and not some other request that we made (we made no other requests in this example)

Communicating with a Service - 2. Pending Result

public class MyActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

...}

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if(requestCode == 15) {

if(resultCode == 1)Toast.makeText(this, "Result is GOOD", Toast.LENGTH_SHORT).show()

elseToast.makeText(this, "Result is BAD",

Toast.LENGTH_SHORT).show()

}}

}

If the Service called PendingIntent.send() with any value other than 1, then we choose to treat it as an error (you can treat it however you want to)

Communicating with a Service - 2. Pending Result

See ServicePendingResult.tar

Communicating with a Service - 3. Messenger

3. Messenger

• A Messenger sends messages to an activity’s Handler

• Use the Messenger as the bridge between an Activity

and a Service

• A Messenger is Parcelable!

o Which means it can be put into an Intent extra.

• The Activity calling startService() would attach a

Messenger as an extra in the Intent

• The Service would obtain that Messenger from the

Intent

Communicating with a Service - 3. Messenger

When the service wants to tell the activity about some event that just occurred, it would:

o Call Message.obtain() to get an empty Message object Message msg = Message.obtain();

o Populate that Message object with whatever data the service wishes to pass to the activity. int result = Activity.RESULT_CANCELED; msg.arg1 = result;

o Call send() on the Messenger, supplying the Message as a parameter messenger.send(msg);

o The activity’s Handler object will receive the message via handleMessage(). This will be on the main application thread so that updates to the

UI or whatever you would like can happen.

Communicating with a Service - 3. Messenger

Communicating with a Service - 3. Messenger

3. Messenger Example

This code example involves the following components

• Activity• Service

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

Let's start with our Activity

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

We create another class inside of our Activity! We'll get back to this shortly

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

For now, just note that we reference it as handler

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

Let's take some action after a Button is clicked

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

So we want to start a Service at some point

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

And we'er adding some Messenger Object to our Bundle, hmm ...

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

And we'er adding some Messenger Object to our Bundle, hmm ...

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

Let's start our Service and see what happens

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

Here's our Service

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

Nothing new here, this gets called because we started the IntentService

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

Try to get a Bundle

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

Make sure it's not null. If it's null and you try you use it you'll get Force Close

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

We can get the Messenger that was passed via the Bundle!

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

Let's create a new Message. Message.obtain() is nothing super special here, it just returns a new Message() object more efficiently

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

This Bundle is DIFFERENT than the one we got using intent.getExtras()

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

We had a boolean value to the results Bundle

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

We add the Bundle to the Message (not the Messenger)!

Communicating with a Service - 3. Messenger

public class MyService extends IntentService {public MyService() {

super("MyService");}

@Override protected void onHandleIntent(Intent intent) {for(int i = 0; i < 50000000; i++);

Bundle extras = intent.getExtras();if(extras != null) {

Messenger messenger = (Messenger) extras.get("messenger");Message msg = Message.obtain();Bundle results = new Bundle();results.putBoolean("success", true);msg.setData(results);try {

messenger.send(msg);} catch (RemoteException e) {

e.printStackTrace();}

}

}}

Let's try sending the Message via the Messenger. Where does the code go from here?

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

To the handleMessage() callback function of the Handler!

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

Remember we passed handler as an argument to the Messenger object

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

And we packaged the Messenger in our Intent

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

That Intent was used to start our Service

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

And the Service added a Message to the Messenger, and then sent the Message

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

That Message was received by handler

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

The handler can now get the Message, which is packaged in a Bundle

Communicating with a Service - 3. Messenger

public class MyActivity extends Activity {private Handler handler = new Handler() {

@Override public void handleMessage(Message msg) {Bundle results = msg.getData();if(results.getBoolean("success") == true) Toast.makeText(MyActivity.this, "Complete!", Toast.LENGTH_LONG).show();

}};

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button = (Button) findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {

@Overridepublic void onClick(View v) {

Intent myIntent = new Intent(MyActivity.this, MyService.class);myIntent.putExtra("messenger", new Messenger(handler));startService(myIntent);

}});

}}

Note that the reason we can pass an instance of Messenger to Intent.puExtra() is because Messenger is Parcelable

DownloadService

This example from Mark Murphy uses• Activity• Service• Messenger

to download a file, given a URL

See DownloaderServiceExample.tar

DownloadManager

• DownloadManager is available in 2.3 and higher (API Level 9)o Use this instead of DownloadService if you have a

device that supports this

See DownloadManagerExample.tar

• This example by Lars Vogel uses a single Activity

MediaPlayer

The Android MediaPlayer class allows you to play songs and video

It is not an Activity, but can be used by an Activity or Service

MediaPlayer

There are several ways you can playback music using a MediaPlayer

We'll only be looking at playing back from some location on our devices

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

A simple Activity

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

You're provided with a convenient way to create a MediaPlayer by passing it a resource id

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

Here I took an MP3 file named palace.mp3, created the directory res/raw, and placed the MP3 in said directory

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

res/raw is another special Android directory, used for general-purpose files (e.g,. an audio clip, a CSV file ofaccount information)

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start(); for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

Start playing the MP3, so simple

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

Wait for some time to elapse ...

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();

}

}

Try to go back to the beginning of the track

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;mp.stop();

mp.release();

}

}

Wait for some time to elapse

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();mp.release();

}

}

Stop playback

MediaPlayer - Examplepublic class MediaPlayerExampleActivity extends Activity {

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

MediaPlayer mp = MediaPlayer.create(this, R.raw.palace);

mp.start();

for(int i = 0; i < 100000000; i++) ;

try{

mp.seekTo(0);

} catch (IllegalStateException e) { }

for(int i = 0; i < 50000000; i++) ;

mp.stop();

mp.release();}

}

Free up the resources! This is important to performance (battery life!)

State Diagram of MediaPlayer

AsyncTask• enables proper and easy use of the UI thread

• the main thread in Android is the UI thread

• the actions in the UI thread are queued!o when you press a Button, it has to be redrawn on the screeno pressing another Button before the previous is redrawn will queue

• allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

AsyncTask looks a bit awkward ...Because it uses Generic Types

• 3 generic types are required when extending AsyncTasko The three types used by an asynchronous task are

the following:1. Params, the type of the parameters sent to the task

upon execution2. Progress, the type of the progress units published

during the background computation3. Result, the type of the result of the background

computation

AsyncTask - 4 stepsWhen an asynchronous task is executed, the task goes through 4 steps

1. onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.

2. doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also usepublishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step

3. onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is 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

4. onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

AsyncTask - 4 steps

See AsyncTaskFullExample.tar

top related