am eb3547b3: Add API demo for services that run in the foreground.

Merge commit 'eb3547b3d0678ad16a602d342cf81dc64e03d9b7' into eclair-mr2

* commit 'eb3547b3d0678ad16a602d342cf81dc64e03d9b7':
  Add API demo for services that run in the foreground.
This commit is contained in:
Dianne Hackborn
2009-12-01 17:05:18 -08:00
committed by Android Git Automerger
6 changed files with 322 additions and 0 deletions

View File

@@ -249,6 +249,15 @@
</intent-filter>
</activity>
<service android:name=".app.ForegroundService" />
<activity android:name=".app.ForegroundServiceController" android:label="@string/activity_foreground_service_controller">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<!-- Alarm Samples -->
<receiver android:name=".app.OneShotAlarm" android:process=":remote" />

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Demonstrates starting and stopping a local service.
See corresponding Java code com.android.sdk.app.LocalSerice.java. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
android:gravity="center_horizontal"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingBottom="4dip"
android:text="@string/foreground_service_controller"/>
<Button android:id="@+id/start_foreground"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/start_service_foreground">
<requestFocus />
</Button>
<Button android:id="@+id/start_background"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/start_service_background">
<requestFocus />
</Button>
<Button android:id="@+id/stop"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/stop_service">
</Button>
</LinearLayout>

View File

@@ -139,6 +139,15 @@
<string name="service_created">Service created.</string>
<string name="service_destroyed">Service destroyed.</string>
<string name="foreground_service_started">Service is in the foreground</string>
<string name="foreground_service_label">Sample Foreground Service</string>
<string name="activity_foreground_service_controller">App/Service/Foreground Service Controller</string>
<string name="foreground_service_controller">This demonstrates how you can
implement services that run in the foreground when needed.</string>
<string name="start_service_foreground">Start Service Foreground</string>
<string name="start_service_background">Start Service Background</string>
<string name="one_shot_received">The one-shot alarm has gone off</string>
<string name="repeating_received">The repeating alarm has gone off</string>

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.apis.app;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import com.example.android.apis.R;
/**
* This is an example of implementing an application service that can
* run in the "foreground". It shows how to code this to work well by using
* the improved Android 2.0 APIs when available and otherwise falling back
* to the original APIs. Yes: you can take this exact code, compile it
* against the Android 2.0 SDK, and it will against everything down to
* Android 1.0.
*/
public class ForegroundService extends Service {
static final String ACTION_FOREGROUND = "com.example.android.apis.FOREGROUND";
static final String ACTION_BACKGROUND = "com.example.android.apis.BACKGROUND";
private static final Class[] mStartForegroundSignature = new Class[] {
int.class, Notification.class};
private static final Class[] mStopForegroundSignature = new Class[] {
boolean.class};
private NotificationManager mNM;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];
@Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
try {
mStartForeground = getClass().getMethod("startForeground",
mStartForegroundSignature);
mStopForeground = getClass().getMethod("stopForeground",
mStopForegroundSignature);
} catch (NoSuchMethodException e) {
// Running on an older platform.
mStartForeground = mStopForeground = null;
}
}
// This is the old onStart method that will be called on the pre-2.0
// platform. On 2.0 or later we override onStartCommand() so this
// method will not be called.
@Override
public void onStart(Intent intent, int startId) {
handleCommand(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
void handleCommand(Intent intent) {
if (ACTION_FOREGROUND.equals(intent.getAction())) {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.foreground_service_started);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.stat_sample, text,
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, ForegroundServiceController.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.local_service_label),
text, contentIntent);
startForegroundCompat(R.string.foreground_service_started, notification);
} else if (ACTION_BACKGROUND.equals(intent.getAction())) {
stopForegroundCompat(R.string.foreground_service_started);
}
}
/**
* This is a wrapper around the new startForeground method, using the older
* APIs if it is not available.
*/
void startForegroundCompat(int id, Notification notification) {
// If we have the new startForeground API, then use it.
if (mStartForeground != null) {
mStartForegroundArgs[0] = Integer.valueOf(id);
mStartForegroundArgs[1] = notification;
try {
mStartForeground.invoke(this, mStartForegroundArgs);
} catch (InvocationTargetException e) {
// Should not happen.
Log.w("ApiDemos", "Unable to invoke startForeground", e);
} catch (IllegalAccessException e) {
// Should not happen.
Log.w("ApiDemos", "Unable to invoke startForeground", e);
}
return;
}
// Fall back on the old API.
setForeground(true);
mNM.notify(id, notification);
}
/**
* This is a wrapper around the new stopForeground method, using the older
* APIs if it is not available.
*/
void stopForegroundCompat(int id) {
// If we have the new stopForeground API, then use it.
if (mStopForeground != null) {
mStopForegroundArgs[0] = Boolean.TRUE;
try {
mStopForeground.invoke(this, mStopForegroundArgs);
} catch (InvocationTargetException e) {
// Should not happen.
Log.w("ApiDemos", "Unable to invoke stopForeground", e);
} catch (IllegalAccessException e) {
// Should not happen.
Log.w("ApiDemos", "Unable to invoke stopForeground", e);
}
return;
}
// Fall back on the old API. Note to cancel BEFORE changing the
// foreground state, since we could be killed at that point.
mNM.cancel(id);
setForeground(false);
}
@Override
public void onDestroy() {
// Make sure our notification is gone.
stopForegroundCompat(R.string.foreground_service_started);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.apis.app;
// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import com.example.android.apis.R;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* <p>Example of explicitly starting and stopping the {@link ForegroundService}.
*/
public class ForegroundServiceController extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.foreground_service_controller);
// Watch for button clicks.
Button button = (Button)findViewById(R.id.start_foreground);
button.setOnClickListener(mForegroundListener);
button = (Button)findViewById(R.id.start_background);
button.setOnClickListener(mBackgroundListener);
button = (Button)findViewById(R.id.stop);
button.setOnClickListener(mStopListener);
}
private OnClickListener mForegroundListener = new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND);
intent.setClass(ForegroundServiceController.this, ForegroundService.class);
startService(intent);
}
};
private OnClickListener mBackgroundListener = new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(ForegroundService.ACTION_BACKGROUND);
intent.setClass(ForegroundServiceController.this, ForegroundService.class);
startService(intent);
}
};
private OnClickListener mStopListener = new OnClickListener() {
public void onClick(View v) {
stopService(new Intent(ForegroundServiceController.this,
ForegroundService.class));
}
};
}

View File

@@ -86,6 +86,15 @@
service_start_arguments_controller.xml</a>
</dl>
</dd>
<dt><a href="ForegroundServiceController.html">Foreground Service Controller</a></dt>
<dd>Controls the service class
<a href="ForegroundService.html">ForegroundService</a>, which shows how you
can write a Service that runs in the foreground and works on both pre-2.0
and post-2.0 versions of the platform. This example will selectively use
the new foreground APIs that were introduced in Android 2.0 if they are
available.</dd>
</dl>
<h3>Alarm</h3>