Android Chapter11 Services Notifications
Android Chapter11 Services Notifications
Services &
Notifications
Android
Services
Victor Matos
Cleveland State University
Portions of this page are reproduced from work created and shared by Google and used according to terms
described in the Creative Commons 3.0 Attribution License.
Services
Android Services
This means that, if your service is going to do any CPU intensive (such as MP3
playback) or blocking (such as networking) operations, it should spawn its own
thread in which to do that work.
• Each startService call invokes the onStart() method of the service class,
however the service is started only with the first call.
• Only one stopService() call is needed to stop the service, no matter how
many times startService() was called.
4
Taken from: http://developer.android.com/guide/components/services.html
Services
Service Life Cycle
5
Services
Service Life Cycle
The entire lifetime of a service happens between the time onCreate() is called
and the time onDestroy() returns.
Like an activity, a service does its initial setup in onCreate(), and releases all
remaining resources in onDestroy().
For example, a music playback service could create the thread where the
music will be played in onCreate(), and then stop the thread in onDestroy().
6
Services
onStartCommand()
Input parameters:
intent - The Intent supplied to startService(Intent)
flags - Additional data about this start request
startId - A unique integer representing this specific request to start
Output result:
The return value indicates what semantics the system should use for the service's
current started state.
START_STICKY
START_NOT_STICKY
START_REDELIVER_INTENT
7
Services
Broadcast Receiver Lifecycle
A Broadcast Receiver is an application class that listens for global Intents that are
broadcasted to any one who bothers to listen, rather than being sent to a single target
application/activity.
The system delivers a broadcast Intent to all interested broadcast
receivers, which handle the Intent sequentially.
8
Services
Registering a Broadcast Receiver
9
Services
Broadcast Receiver Lifecycle
onReceive
A broadcast receiver has a single callback method:
10
Services
Services, BroadcastReceivers and the AdroidManifest
See example
11
Services
Services, BroadcastReceivers and the AdroidManifest
<?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-sdk android:minSdkVersion="10" ></uses-sdk>
<activity android:name=".MyServiceDriver2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="MyBroadcastReceiver">
<intent-filter>
<action android:name = "matos.action.GOSERVICE2" />
</intent-filter>
</receiver>
</application>
</manifest>
12
Services
Types of Broadcasts
14
Services
Example: Main Steps – The Service
The Service uses its onStart method to do the following:
2. Prepare the extra data (‘myServiceData’) to be sent with the intent to the
receiver(s)
sendBroadcast(myFilteredResponse);
15
Services
Example: Steps – The Driver (again)
The main activity is responsible for cleanly terminating the service. Do the
following
stopService(new Intent(intentMyService) );
2. Use the service’s onDestroy method to assure that all of its running threads
are terminated and the receiver is unregistered.
unregisterReceiver(receiver);
16
Services
Example 1. A very Simple Service
The main application starts a service. The service prints lines on the LogCat
until the main activity stops the service. No IPC occurs in the example.
public class TestMyService1 extends Activity implements OnClickListener {
TextView txtMsg;
ComponentName service;
Intent intentMyService1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtMsg = (TextView) findViewById(R.id.txtMsg);
findViewById(R.id.btnStopService).setOnClickListener(this);
intentMyService1 = new Intent(this, MyService1.class);
service = startService(intentMyService1);
txtMsg.setText("MyService1 started\n (see LogCat)");
}
17
Services
Example 1. A very Simple Service
The main application starts a service. The service prints lines on the LogCat
until the main activity stops the service. No IPC occurs in the example.
@Override
public void onClick(View v) {
// assume: v.getid == R.id.btnStopService
try {
stopService(intentMyService1);
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), 1).show();
}
}//onClick
}//class
18
Services
Example 1. cont.
//non CPU intensive service running the main task in its main thread
package cis.matos;
import . . .
public class MyService1 extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
Log.e ("<<MyService1-onStart>>", "I am alive-1!");
Log.e ("<<MyService1-onStart>>", "I did something");
}
@Override
public void onDestroy() {
Log.e ("<<MyService1-onDestroy>>", "I am dead-1");
}
19
}//MyService1
Services
Example 1. cont.
<EditText
android:id="@+id/txtMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:layout_margin="10dp" />
<Button
android:id="@+id/btnStopService"
android:layout_width="204dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=" Stop Service1" />
</LinearLayout>
22
Services
Example 2. A More Interesting Activity-Service Interaction
6. At some point the main activity stops the service and finishes executing.
23
Services
Example 2. Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btnStopService"
android:layout_width="151dip"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Stop Service" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/txtMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</ScrollView>
</LinearLayout> 24
Services
Example 2. 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" >
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light">
<activity
android:name=".MyServiceDriver3"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest> 25
Services
Example 2. Main Activity 1 of 3
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtMsg = (TextView) findViewById(R.id.txtMsg);
}//onCreate
26
Services
Example 2. Main Activity 2 of 3
stopService(intentMyService3);
@Override
protected void onDestroy() {
super.onDestroy();
try {
stopService(intentMyService3);
unregisterReceiver(receiver);
} catch (Exception e) {
}//MyMainLocalReceiver
}//MyServiceDriver3
28
Services
Example 2. Service 1 of 2
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
Log.e ("<<MyService3-onStart>>", "I am alive-3!");
intentDataForMyClient.putExtra("service3Data", msg);
sendBroadcast(intentDataForMyClient);
} catch (Exception e) {
e.printStackTrace();
}
}//for
}//run
});
serviceThread.start();
}//onStart
@Override
public void onDestroy() {
super.onDestroy();
Log.e ("<<MyService3-onDestroy>>", "I am Dead-3");
isRunning = false;
}//onDestroy
}//MyService3
30
Services
Example 3. An App Connected to Multiple Services
Main App
TestMyService4
(Manages UI)
Broadcast Listener
MyService4
(Music Player)
MyService5Async
(Fibonacci Number Generator)
MyService6
(GPS Coordinates)
31
Services
Example 3. An App Connected to Multiple Services
33
Services
Example 3. MainActivity: TestMyService4.java
package csu.matos;
import . . .
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtMsg = (TextView) findViewById(R.id.txtMsg);
findViewById(R.id.btnStart4).setOnClickListener(this);
findViewById(R.id.btnStop4).setOnClickListener(this);
findViewById(R.id.btnStart5).setOnClickListener(this);
findViewById(R.id.btnStop5).setOnClickListener(this);
findViewById(R.id.btnStart6).setOnClickListener(this);
findViewById(R.id.btnStop6).setOnClickListener(this);
34
Services
Example 3. MainActivity: TestMyService4.java
}// onCreate
35
Services
Example 3. MainActivity: TestMyService4.java
@Override
public void onClick(View v) {
if (v.getId() == R.id.btnStart4) {
Log.e("MAIN", "onClick: starting service4");
startService(intentCallService4);
} else if (v.getId() == R.id.btnStop4) {
Log.e("MAIN", "onClick: stopping service4");
stopService(intentCallService4);
} else if (v.getId() == R.id.btnStart5) {
Log.e("MAIN", "onClick: starting service5");
startService(intentCallService5);
} else if (v.getId() == R.id.btnStop5) {
Log.e("MAIN", "onClick: stopping service5");
stopService(intentCallService5);
} else if (v.getId() == R.id.btnStart6) {
Log.e("MAIN", "onClick: starting service6");
startService(intentCallService6);
} else if (v.getId() == R.id.btnStop6) {
Log.e("MAIN", "onClick: stopping service6");
stopService(intentCallService6);
}
}// onClick
36
Services
Example 3. MainActivity: TestMyService4.java
public class MyEmbeddedBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("MAIN>>>", "ACTION: " + intent.getAction());
if (intent.getAction().equals("matos.action.GOSERVICE5")) {
String service5Data = intent.getStringExtra("MyService5DataItem");
Log.e("MAIN>>>", "Data received from Service5: " + service5Data);
txtMsg.append("\nService5Data: > " + service5Data);
} else if (intent.getAction().equals("matos.action.GPSFIX")) {
double latitude = intent.getDoubleExtra("latitude", -1);
double longitude = intent.getDoubleExtra("longitude", -1);
String provider = intent.getStringExtra("provider");
String service6Data = provider
+ " lat: " + Double.toString(latitude)
+ " lon: " + Double.toString(longitude);
Log.e("MAIN>>>", "Data received from Service6: " + service6Data);
txtMsg.append("\nService6Data: > " + service6Data);
}
}//onReceive
}// MyEmbeddedBroadcastReceiver
}// TestService4 class
37
Services
Example 3. MyService4 – A Music Player
package csu.matos;
import . . .
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Toast.makeText(this, "MyService4 Created", Toast.LENGTH_LONG).show();
Log.e("MyService4", "onCreate");
boolIsServiceCreated = true;
player = MediaPlayer.create(getApplicationContext(),
R.raw.good_bad_ugly);
}
38
Services
Example 3. MyService4 – A Music Player
@Override
public void onDestroy() {
Toast.makeText(this, "MyService4 Stopped", Toast.LENGTH_LONG).show();
Log.e("MyService4", "onDestroy");
player.stop();
player.release();
player = null;
}
@Override
public void onStart(Intent intent, int startid) {
if (player.isPlaying())
Toast.makeText(this, "MyService4 Already Started " + startid,
Toast.LENGTH_LONG).show();
else
Toast.makeText(this, "MyService4 Started " + startid,
Toast.LENGTH_LONG).show();
Log.e("MyService4", "onStart");
player.start();
}
}
39
Services
Example 3. MyService5Async – A Slow Fibonacci Number Gen.
package csu.matos;
import . . .
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
40
Services
Example 3. MyService5Async – A Slow Fibonacci Number Gen.
@Override
public void onStart(Intent intent, int startId) {
Log.e ("<<MyService5Async-onStart>>", "I am alive-5Async!");
// we place the slow work of the service in an AsynTask
// so the response we send our caller who run
// a "startService(...)" method gets a quick OK from us.
@Override
public void onDestroy() {
//super.onDestroy();
Log.e ("<<MyService5Async-onDestroy>>", "I am dead-5-Async");
isRunning = false;
}//onDestroy 41
Services
Example 3. MyService5Async – A Slow Fibonacci Number Gen.
public class ComputeFibonacciRecursivelyTask extends AsyncTask <
Integer, Integer, Integer > {
@Override
protected Integer doInBackground(Integer... params) {
for (int i=params[0]; i<params[1]; i++){
Integer fibn = fibonacci(i);
publishProgress(i, fibn);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Intent intentFilter5 = new Intent("matos.action.GOSERVICE5");
String data = "dataItem-5-fibonacci-AsyncTask"
+ values[0] + ": " + values[1];
intentFilter5.putExtra("MyService5DataItem", data);
sendBroadcast(intentFilter5);
// (next id not really needed!!! - we did the broadcasting already)
Message msg = handler.obtainMessage(5, data);
handler.sendMessage(msg);
}
}// ComputeFibonacciRecursivelyTask
}//MyService5 42
Services
Example 3. MyService6 – A GPS Service broadcasting locations.
package csu.matos;
Import . . .
Thread serviceThread;
LocationManager lm;
GPSListener myLocationListener;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
43
Services
Example 3. MyService6 – A GPS Service broadcasting locations.
@Override
public void onStart(Intent intent, int startId) {
Log.e("<<MyGpsService-onStart>>", "I am alive-GPS!");
}// run
});
serviceThread.start();
}// onStart
44
Services
Example 3. MyService6 – A GPS Service broadcasting locations.
public void getGPSFix_Version1() {
} catch (Exception e) {
e.printStackTrace();
}
46
Services
Example 3. MyService6 – A GPS Service broadcasting locations.
@Override
public void onDestroy() {
super.onDestroy();
Log.e("<<MyGpsService-onDestroy>>", "I am dead-GPS");
try {
lm.removeUpdates(myLocationListener);
isRunning = false;
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage(), 1).show();
}
}// onDestroy
47
Services
Example 3. MyService6 – A GPS Service broadcasting locations.
private class GPSListener implements LocationListener {
public void onLocationChanged(Location location) {
// capture location data sent by current provider
double latitude = location.getLatitude();
double longitude = location.getLongitude();
// assemble data bundle to be broadcasted
Intent myFilteredResponse = new Intent(GPS_FILTER);
myFilteredResponse.putExtra("latitude", latitude);
myFilteredResponse.putExtra("longitude", longitude);
myFilteredResponse.putExtra("provider", location.getProvider());
Log.e(">>GPS_Service<<", "Lat:" + latitude + " lon:" + longitude);
// send the location data out
sendBroadcast(myFilteredResponse);
}
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:theme="@style/AppTheme" >
<activity
android:name=".TestService4"
android:label="@string/title_activity_test_service4"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService4"/>
<service android:name=".MyService5Async" />
<service android:name=".MyService6" />
</application>
</manifest> 49
Services
Example 3. Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btnStart4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="15"
android:text="Start Service4 (Music Player)" />
<Button
android:id="@+id/btnStop4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="15"
android:text="Stop Service4 (Music Player)" /> 50
Services
Example 3. Layout
<Button
android:id="@+id/btnStart5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="15"
android:text="Start Service5 (Fibonacci)" />
<Button
android:id="@+id/btnStop5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="15"
android:text="Stop Service5 (Fibonacci)" />
<Button
android:id="@+id/btnStart6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="15"
android:text="Start Service6 (GPS Fix)" />
<Button
android:id="@+id/btnStop6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="15"
android:text="Stop Service6 (GPS Fix)" /> 51
Services
Example 3. Layout
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/txtMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp" />
</ScrollView>
</LinearLayout>
</LinearLayout>
52
Android
Notifications
Victor Matos
Cleveland State University
Portions of this page are reproduced from work created and shared by Google and used according to terms
described in the Creative Commons 3.0 Attribution License.
Notifications
What is a Notification?
After opening the Notification Panel the user may choose to click on a
selection and execute an associated activity.
54
Notifications
What is a Notification?
Notification shown
on the status line
Drag down
Click on
Notification
Panel to
execute
associated
application
55
Notifications
Notification Manager
This class notifies the user of events that happen in the background.
1. A persistent icon that goes in the status bar and is accessible through the
launcher, (when the user selects it, a designated Intent can be launched),
56
Notifications – Since Jelly Bean 4.0
Base Layout
Optional Entries
1. Additional lines
2. Up to three actions
3. A summary line
57
Notifications – Since Jelly Bean 4.0
Extended Layout
Sender’s
Icon / Photo
Extra lines
Up to 3
Actions to
call
Summary
Activity to
be called
58
Notifications
Notification Manager
Example:
notificationManager = (NotificationManager)
getSystemService (servName);
59
Notifications
Notification Builder
A convenient way to set up various fields of a Notification
Example:
60
Notifications
Example
61
Notifications
Example
62
Notifications
Example
63
Notifications
Example: MainActivity
package com.example.mynotificationmanager;
import . . .
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.btnBig).setOnClickListener(this);
findViewById(R.id.btnCancel).setOnClickListener(this);
}// onCreate
@SuppressLint("NewApi")
public void createBigNotification(View view) {
65
Notifications
Example: MainActivity
Notification noti = new Notification.InboxStyle(baseNotification)
.addLine("Line-1")
.addLine("Line-2")
.addLine("Line-2")
.setSummaryText("SUMMARY-Line-1 here")
.build();
notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
// Hide the notification after its selected
noti.flags |= Notification.FLAG_AUTO_CANCEL;
// notification ID is 12345
notificationManager.notify(12345, noti);
}// createBigNotification
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnBig:
createBigNotification(v);
break;
66
Notifications
Example: MainActivity
case R.id.btnCancel :
try {
if ( notificationManager != null){
notificationManager.cancel(NOTIFICATION_ID);
}
} catch (Exception e) {
Log.e("<<MAIN>>", e.getMessage() );
}
break;
}
}// onClick
}// class
67
Notifications
Example: NotificationReceiverActivity
package com.example.mynotificationmanager;
import . . .
68
Notifications
Example: Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mynotificationmanager"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="14" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" ><activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<activity android:name=".NotificationReceiverActivity2"
android:icon="@drawable/icon2" >
</activity>
<activity android:name=".NotificationReceiverActivity3"
android:icon="@drawable/icon3" >
</activity>
</application>
</manifest>
70
Notifications
Example - Layout: main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btnBig"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Create Big Notification"
android:ems="20" >
</Button>
<Button
android:id="@+id/btnCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel Notification"
android:ems="20" >
</Button>
</LinearLayout>
71
Notifications
Example - Layout: main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/txtMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Called from the MASTER notification" >
</TextView>
</LinearLayout>
72
Notifications
Use custom view
// Define remote views from custom design xml
RemoteViews contentView = new RemoteViews(getPackageName(),
R.layout.notification_content_view);
// Set onOnClickPendingIntent
contentView.setOnClickPendingIntent(R.id.button_play, pendingIntent);
73