summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Malin <jmalin@google.com>2010-06-05 14:03:42 -0700
committerJoe Malin <jmalin@google.com>2010-08-18 11:39:13 -0700
commit6878d8cf8bdff6f9111a8071db360b5f3e2cb7f1 (patch)
tree145a11fbeeacb94838aeea312eebfa6d9e05b4aa
parent1164f90b8ace302a5b6827e27459a6d8be975eb3 (diff)
downloadandroid_development-6878d8cf8bdff6f9111a8071db360b5f3e2cb7f1.tar.gz
android_development-6878d8cf8bdff6f9111a8071db360b5f3e2cb7f1.tar.bz2
android_development-6878d8cf8bdff6f9111a8071db360b5f3e2cb7f1.zip
Sample app and test package for a Service
Change-Id: I6589a1b761f5c40b86f1319c30ead2409113b647
-rw-r--r--samples/Alarm/AndroidManifest.xml54
-rw-r--r--samples/Alarm/_index.html29
-rw-r--r--samples/Alarm/res/drawable/icon.pngbin0 -> 5198 bytes
-rwxr-xr-xsamples/Alarm/res/drawable/stat_sample.pngbin0 -> 364 bytes
-rw-r--r--samples/Alarm/res/layout/main.xml44
-rw-r--r--samples/Alarm/res/values/strings.xml29
-rw-r--r--samples/Alarm/src/com/example/android/newalarm/AlarmActivity.java133
-rw-r--r--samples/Alarm/src/com/example/android/newalarm/AlarmService.java216
-rw-r--r--samples/Alarm/tests/AndroidManifest.xml54
-rw-r--r--samples/Alarm/tests/_index.html50
-rw-r--r--samples/Alarm/tests/src/com/example/android/newalarm/AlarmServiceTest.java86
11 files changed, 695 insertions, 0 deletions
diff --git a/samples/Alarm/AndroidManifest.xml b/samples/Alarm/AndroidManifest.xml
new file mode 100644
index 000000000..6a7a831a8
--- /dev/null
+++ b/samples/Alarm/AndroidManifest.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<!--
+ Declares the contents of this Android application. The xmlns:android
+ attribute brings in the Android platform namespace, and the
+ "package" attribute provides a unique name for the application.
+ If you use this file as a template in your own application, you must change
+ the package name from "com.example.android" to one that you own or have
+ control over.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.newalarm"
+ android:versionCode="2"
+ android:versionName="2.0">
+ <!--
+ Declares the application, its icon, and its visible label
+ -->
+ <application
+ android:icon="@drawable/icon"
+ android:label="@string/app_name">
+ <!--
+ Declares the activity's class name and visible label. The leading "." indicates
+ that the name should be preceded by the application's Android package name.
+ -->
+ <activity
+ android:name=".AlarmActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <service
+ android:name=".AlarmService"
+ android:label="@string/alarm_service"
+ android:process="com.example.android.newalarm">
+ </service>
+ </application>
+ <uses-sdk android:targetSdkVersion="4" android:minSdkVersion="3"/>
+</manifest>
diff --git a/samples/Alarm/_index.html b/samples/Alarm/_index.html
new file mode 100644
index 000000000..dff51ce94
--- /dev/null
+++ b/samples/Alarm/_index.html
@@ -0,0 +1,29 @@
+<p>
+ This sample is a revised version of the AlarmService functionality included in the
+ ApiDemos sample application. It is used as the application under test
+ for the <a href="../AlarmServiceTest/index.html">Alarm Service Test</a>
+ sample test application.
+</p>
+<p>
+ This application demonstrates a simple Android service that is started when needed by
+ <code>Context.startService(Intent)</code> and stops itself when its work is done. You can
+ use this type of service to move long-running or periodic tasks into the background. For
+ example, you could use this type of service to perform data synchronization.
+</p>
+<p>
+ In the sample, the service simply runs for 15 seconds and then stops itself. The wait is
+ implemented in a separate thread that uses a thread-safe object. This illustrates how to
+ set up a service that runs multiple threads that depend on one or more objects that must be
+ made thread-safe.
+</p>
+<p>
+ The application also contains the <code>AlarmActivity</code> activity that is a client of the
+ service. You use the activity to control when the service starts and stops. By default, the
+ activity fires off the service every thirty seconds. In effect, the service starts after
+ thirty seconds, runs for 15 seconds, stops, and then runs again automatically in another
+ 15 seconds. You also use the client to stop this cycle.
+</p>
+<p>
+ The test application <a href="tests/index.html">AlarmServiceTest</a>
+ shows you how to set up a test of this service.
+</p>
diff --git a/samples/Alarm/res/drawable/icon.png b/samples/Alarm/res/drawable/icon.png
new file mode 100644
index 000000000..5ae7701a8
--- /dev/null
+++ b/samples/Alarm/res/drawable/icon.png
Binary files differ
diff --git a/samples/Alarm/res/drawable/stat_sample.png b/samples/Alarm/res/drawable/stat_sample.png
new file mode 100755
index 000000000..6c9ba0a97
--- /dev/null
+++ b/samples/Alarm/res/drawable/stat_sample.png
Binary files differ
diff --git a/samples/Alarm/res/layout/main.xml b/samples/Alarm/res/layout/main.xml
new file mode 100644
index 000000000..3d79e2ba5
--- /dev/null
+++ b/samples/Alarm/res/layout/main.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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/alarm_service"/>
+ <Button android:id="@+id/start_alarm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/start_alarm_service">
+ <requestFocus />
+ </Button>
+
+ <Button android:id="@+id/stop_alarm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/stop_alarm_service" />
+</LinearLayout>
+
diff --git a/samples/Alarm/res/values/strings.xml b/samples/Alarm/res/values/strings.xml
new file mode 100644
index 000000000..18a34cc39
--- /dev/null
+++ b/samples/Alarm/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<resources>
+ <string name="app_name">Alarm</string>
+ <string name="alarm_service">
+ This shows how to schedule a repeating alarm that starts a service.</string>
+ <string name="start_alarm_service">Start Alarm Service</string>
+ <string name="stop_alarm_service">Stop Alarm Service</string>
+ <string name="repeating_started">
+ Repeating timer started. Starts AlarmService every 30 seconds.</string>
+ <string name="alarm_service_started">The sample service is running.</string>
+ <string name="alarm_service_label">Sample Alarm Service</string>
+ <string name="alarm_service_finished">The sample service is no longer running.</string>
+ <string name="repeating_stopped">
+ Repeating timer stopped. AlarmService will no longer be started.</string>
+</resources>
diff --git a/samples/Alarm/src/com/example/android/newalarm/AlarmActivity.java b/samples/Alarm/src/com/example/android/newalarm/AlarmActivity.java
new file mode 100644
index 000000000..d26507d05
--- /dev/null
+++ b/samples/Alarm/src/com/example/android/newalarm/AlarmActivity.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010 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.newalarm;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+/**
+ * This is the activity that controls AlarmService.
+ * <p>
+ * When the user clicks the "Start Alarm Service" button, it triggers a repeating countdown
+ * timer. Every thirty seconds, the timer starts AlarmService, which then runs for 15 seconds
+ * and shuts itself down.
+ * </p>
+ * <p>
+ * When the user clicks the "Stop Alarm Service" button, it stops the countdown timer.
+ * </p>
+ */
+
+public class AlarmActivity extends Activity {
+ // 30 seconds in milliseconds
+ private static final long THIRTY_SECONDS_MILLIS = 30 * 1000;
+
+ // An intent for AlarmService, to trigger it as if the Activity called startService().
+ private PendingIntent mAlarmSender;
+
+ // Contains a handle to the system alarm service
+ private AlarmManager mAlarmManager;
+
+ /**
+ * This method is called when Android starts the activity. It initializes the UI.
+ * <p>
+ * This method is automatically called when Android starts the Activity
+ * </p>
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Create a PendingIntent to trigger a startService() for AlarmService
+ mAlarmSender = PendingIntent.getService( // set up an intent for a call to a service
+ AlarmActivity.this, // the current context
+ 0, // request code (not used)
+ new Intent(AlarmActivity.this, AlarmService.class), // A new Service intent
+ 0 // flags (none are required for a service)
+ );
+
+ // Creates the main view
+ setContentView(R.layout.main);
+
+ // Finds the button that starts the repeating countdown timer
+ Button button = (Button)findViewById(R.id.start_alarm);
+
+ // Sets the listener for the start button
+ button.setOnClickListener(mStartAlarmListener);
+
+ // Finds the button that stops countdown timer
+ button = (Button)findViewById(R.id.stop_alarm);
+
+ // Sets the listener for the stop button
+ button.setOnClickListener(mStopAlarmListener);
+
+ // Gets the handle to the system alarm service
+ mAlarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
+ }
+
+ // Creates a new anonymous click listener for the start button. It starts the repeating
+ // countdown timer.
+ private OnClickListener mStartAlarmListener = new OnClickListener() {
+ // Sets the callback for when the button is clicked
+ public void onClick(View v) {
+
+ // Sets the time when the alarm will first go off
+ // The Android AlarmManager uses this form of the current time.
+ long firstAlarmTime = SystemClock.elapsedRealtime();
+
+ // Sets a repeating countdown timer that triggers AlarmService
+ mAlarmManager.setRepeating(
+ AlarmManager.ELAPSED_REALTIME_WAKEUP, // based on time since last wake up
+ firstAlarmTime, // sends the first alarm immediately
+ THIRTY_SECONDS_MILLIS, // repeats every thirty seconds
+ mAlarmSender // when the alarm goes off, sends this Intent
+ );
+
+ // Notifies the user that the repeating countdown timer has been started
+ Toast.makeText(
+ AlarmActivity.this, // the current context
+ R.string.repeating_started, // the message to display
+ Toast.LENGTH_LONG // how long to display the message
+ ).show(); // show the message on the screen
+ }
+ };
+
+ // Creates a new anonymous click listener for the stop button. It shuts off the repeating
+ // countdown timer.
+ private OnClickListener mStopAlarmListener = new OnClickListener() {
+ // Sets the callback for when the button is clicked
+ public void onClick(View v) {
+
+ // Cancels the repeating countdown timer
+ mAlarmManager.cancel(mAlarmSender);
+
+ // Notifies the user that the repeating countdown timer has been stopped
+ Toast.makeText(
+ AlarmActivity.this, // the current context
+ R.string.repeating_stopped, // the message to display
+ Toast.LENGTH_LONG // how long to display the message
+ ).show(); // display the message
+ }
+ };
+}
diff --git a/samples/Alarm/src/com/example/android/newalarm/AlarmService.java b/samples/Alarm/src/com/example/android/newalarm/AlarmService.java
new file mode 100644
index 000000000..1f882069d
--- /dev/null
+++ b/samples/Alarm/src/com/example/android/newalarm/AlarmService.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2010 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.newalarm;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.widget.Toast;
+
+/**
+ * <p>
+ * This class implements a service. The service is started by AlarmActivity, which contains a
+ * repeating countdown timer that sends a PendingIntent. The user starts and stops the timer with
+ * buttons in the UI.
+ * </p>
+ * <p>
+ * When this service is started, it creates a Runnable and starts it in a new Thread. The
+ * Runnable does a synchronized lock on the service's Binder object for 15 seconds, then issues
+ * a stopSelf(). The net effect is a new worker thread that takes 15 seconds to run and then
+ * shuts down the entire service. The activity restarts the service after 15 more seconds, when the
+ * countdown timer triggers again.
+ * </p>
+ * <p>
+ * This service is provided as the service under test for the sample test application
+ * AlarmServiceTest.
+ * </p>
+ * <p>
+ * Note: Since this sample is based on the Android 1.5 platform, it does not implement
+ * onStartCommand. See the Javadoc for android.app.Service for more details.
+ * </p>
+ */
+public class AlarmService extends Service {
+ // Defines a label for the thread that this service starts
+ private static final String ALARM_SERVICE_THREAD = "AlarmService";
+
+ // Defines 15 seconds
+ public static final long WAIT_TIME_SECONDS = 15;
+
+ // Define the number of milliseconds in one second
+ public static final long MILLISECS_PER_SEC = 1000;
+
+ /*
+ * For testing purposes, the following variables are defined as fields and set to
+ * package visibility.
+ */
+
+ // The NotificationManager used to send notifications to the status bar.
+ NotificationManager mNotificationManager;
+
+ // An Intent that displays the client if the user clicks the notification.
+ PendingIntent mContentIntent;
+
+ // A Notification to send to the Notification Manager when the service is started.
+ Notification mNotification;
+
+ // A Binder, used as the lock object for the worker thread.
+ IBinder mBinder = new AlarmBinder();
+
+ // A Thread object that will run the background task
+ Thread mWorkThread;
+
+ // The Runnable that is the service's "task". This illustrates how a service is used to
+ // offload work from a client.
+ Runnable mWorkTask = new Runnable() {
+ public void run() {
+ // Sets the wait time to 15 seconds, simulating a 15-second background task.
+ long waitTime = System.currentTimeMillis() + WAIT_TIME_SECONDS * MILLISECS_PER_SEC;
+
+ // Puts the wait in a while loop to ensure that it actually waited 15 seconds.
+ // This covers the situation where an interrupt might have overridden the wait.
+ while (System.currentTimeMillis() < waitTime) {
+ // Waits for 15 seconds or interruption
+ synchronized (mBinder) {
+ try {
+ // Waits for 15 seconds or until an interrupt triggers an exception.
+ // If an interrupt occurs, the wait is recalculated to ensure a net
+ // wait of 15 seconds.
+ mBinder.wait(waitTime - System.currentTimeMillis());
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ // Stops the current service. In response, Android calls onDestroy().
+ stopSelf();
+ }
+ };
+
+ /**
+ * Makes a full concrete subclass of Binder, rather than doing it in line, for readability.
+ */
+ public class AlarmBinder extends Binder {
+ // Constructor. Calls the super constructor to set up the instance.
+ public AlarmBinder() {
+ super();
+ }
+
+ @Override
+ protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+
+ // Call the parent method with the arguments passed in
+ return super.onTransact(code, data, reply, flags);
+ }
+ }
+
+ /**
+ * Initializes the service when it is first started by a call to startService() or
+ * bindService().
+ */
+ @Override
+ public void onCreate() {
+ // Gets a handle to the system mNotification service.
+ mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+ // Updates the status bar to indicate that this service is running.
+ showNotification();
+
+ // Creates a new thread. A new thread is used so that the service's work doesn't block
+ // anything on the calling client's thread. By default, a service runs in the same
+ // process and thread as the client that starts it.
+ mWorkThread = new Thread(
+ null, // threadgroup (in this case, null)
+ mWorkTask, // the Runnable that will run in this thread
+ ALARM_SERVICE_THREAD
+ );
+ // Starts the thread
+ mWorkThread.start();
+ }
+
+ /**
+ * Stops the service in response to the stopSelf() issued when the wait is over. Other
+ * clients that use this service could stop it by issuing a stopService() or a stopSelf() on
+ * the service object.
+ */
+ @Override
+ public void onDestroy() {
+ // Cancels the status bar mNotification based on its ID, which is set in showNotification().
+ mNotificationManager.cancel(R.string.alarm_service_started);
+
+ // Sends a notification to the screen.
+ Toast.makeText(
+ this, // the current context
+ R.string.alarm_service_finished, // the message to show
+ Toast.LENGTH_LONG // how long to keep the message on the screen
+ ).show(); // show the text
+ }
+
+ // Returns the service's binder object to clients that issue onBind().
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ /**
+ * Displays a notification in the status bar that this service is running. This method
+ * also creates an Intent for the AlarmActivity client and attaches it to the notification
+ * line. If the user clicks the line in the expanded status window, the Intent triggers
+ * AlarmActivity.
+ */
+ private void showNotification() {
+ // Sets the text to use for the status bar and status list views.
+ CharSequence notificationText = getText(R.string.alarm_service_started);
+
+ // Sets the icon, status bar text, and display time for the mNotification.
+ mNotification = new Notification(
+ R.drawable.stat_sample, // the status icon
+ notificationText, // the status text
+ System.currentTimeMillis() // the time stamp
+ );
+
+ // Sets up the Intent that starts AlarmActivity
+ mContentIntent = PendingIntent.getActivity(
+ this, // Start the Activity in the current context
+ 0, // not used
+ new Intent(this, AlarmActivity.class), // A new Intent for AlarmActivity
+ 0 // Use an existing activity instance if available
+ );
+
+ // Creates a new content view for the mNotification. The view appears when the user
+ // shows the expanded status window.
+ mNotification.setLatestEventInfo(
+ this, // Put the content view in the current context
+ getText(R.string.alarm_service_label), // The text to use as the label of the entry
+ notificationText, // The text to use as the contents of the entry
+ mContentIntent // The intent to send when the entry is clicked
+ );
+
+ // Sets a unique ID for the notification and sends it to NotificationManager to be
+ // displayed. The ID is the integer marker for the notification string, which is
+ // guaranteed to be unique within the entire application.
+ mNotificationManager.notify(
+ R.string.alarm_service_started, // unique id for the mNotification
+ mNotification // the mNotification object
+ );
+ }
+}
diff --git a/samples/Alarm/tests/AndroidManifest.xml b/samples/Alarm/tests/AndroidManifest.xml
new file mode 100644
index 000000000..868892000
--- /dev/null
+++ b/samples/Alarm/tests/AndroidManifest.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<!--
+ Declare the contents of this Android test package. The xmlns:android
+ attribute brings in the Android platform namespace, and the
+ "package" attribute provides a unique name for the package.
+ If you use this file as a template in your own test package, you must change
+ the package name from "com.example.android" to one that you own or have
+ control over.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.newalarm.test"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <!--
+ Must use the application element to include the uses-library element.
+ -->
+ <application>
+ <!--
+ Tells Android to include this library in the test package's class loader.
+ The test runner is not included by default in a manifest file.
+ -->
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <!--
+ Specifies that the test package requires API platform level 3 (Android 1.5) or above.
+ The installer will not install this package onto a device or emulator that is running an
+ older platform version.
+ -->
+ <uses-sdk android:minSdkVersion="3" />
+ <!--
+ Declares the instrumentation for this application. The instrumentation class is
+ specified by the "name" attribute, and must name a subclass of
+ android.app.Instrumentation. The application that is run by the instrumentation object is
+ specified by the "targetPackage" attribute.
+ -->
+ <instrumentation
+ android:targetPackage="com.example.android.newalarm"
+ android:name="android.test.InstrumentationTestRunner" />
+</manifest>
diff --git a/samples/Alarm/tests/_index.html b/samples/Alarm/tests/_index.html
new file mode 100644
index 000000000..614125dd3
--- /dev/null
+++ b/samples/Alarm/tests/_index.html
@@ -0,0 +1,50 @@
+<p>
+ This sample is the test application for the <a href="../Alarm/index.html">Alarm</a>
+ sample application. It tests the application's <code>AlarmService</code> service.
+</p>
+<p>
+ The test application uses the
+ <a href="../../../reference/android/test/ServiceTestCase.html">
+ <code>ServiceTestCase</code></a> test case class,
+ which extends the JUnit <a href="../../../reference/junit/framework/TestCase.html">
+ <code>TestCase</code></a> class. The test runner is
+ <a href="../../../reference/android/test/InstrumentationTestRunner.html">
+ <code>InstrumentationTestRunner</code></a>.
+</p>
+<p>
+ The application shows how to set up a test application project,
+ how to create the <a href="AndroidManifest.html"><code>AndroidManifest.xml</code></a>
+ file for a test application, and how to set up a test case class for a service. The
+ test case class, <a href="src/com/android/example/newalarm/ServiceAlarmTest.html">
+ <code>AlarmServiceTest</code></a>, contains tests that demonstrate the following
+ Android test patterns:
+</p>
+ <ul>
+ <li>
+ Test setup: The <code>setUp()</code> method re-initializes the state of the
+ service under test before each test is run.
+ </li>
+ <li>
+ Service start: The <code>Service.testServiceCreate()</code> test confirms that the
+ service starts correctly and initializes the variables it needs to provide its
+ services.
+ </li>
+ </ul>
+<p>
+ The <a href="AndroidManifest.html">manifest</a> declares an <code>&lt;instrumentation&gt;</code>
+ element that links the test application with the application under test. Specifically, the
+ element's <code>android:name</code> attribute specifies <code>InstrumentationTestRunner</code>
+ as the instrumentation to use. The <code>android:targetPackage</code> attribute specifies
+ <code>com.android.example.newalarm</code> as the name of the Android package that contains the
+ service under test.
+</p>
+<p class="note">
+ <strong>Note:</strong> <code>AlarmServiceTest.java</code> uses the Java package name
+ <code>com.example.android.newalarm</code>, which is the same package used by service under
+ test, <code>AlarmService.java</code>. This allows the test class to access members in the
+ service under test that are defined with package visibility. To prevent conflicts, though,
+ the generated java file <code>R.java</code> for <code>AlarmServiceTest</code> uses the
+ Java package name <code>com.example.android.newalarm.test</code>. For the same reason, the
+ Android package name for the test application (specified in the manifest file), is
+ <code>com.example.android.newalarm.test</code>.
+</p>
diff --git a/samples/Alarm/tests/src/com/example/android/newalarm/AlarmServiceTest.java b/samples/Alarm/tests/src/com/example/android/newalarm/AlarmServiceTest.java
new file mode 100644
index 000000000..4d6c7aded
--- /dev/null
+++ b/samples/Alarm/tests/src/com/example/android/newalarm/AlarmServiceTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 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.newalarm;
+
+import android.content.Intent;
+import android.test.ServiceTestCase;
+import com.example.android.newalarm.AlarmService;
+
+/**
+ * Test class for the Alarm sample test package. This test class tests the AlarmService
+ * service component.
+ */
+public class AlarmServiceTest extends ServiceTestCase<AlarmService> {
+ // Contains an Intent used to start the service
+ Intent mStartServiceIntent;
+
+ // Contains a handle to the system alarm service
+ AlarmService mService;
+
+ /**
+ * Constructor for the test class. Test classes that are run by InstrumentationTestRunner
+ * must provide a constructor with no arguments that calls the base class constructor as its
+ * first statement.
+ */
+ public AlarmServiceTest() {
+ super(AlarmService.class);
+ }
+
+ /*
+ * Sets up the test fixture. This method is called before each test
+ */
+ @Override
+ protected void setUp() throws Exception {
+
+ super.setUp();
+
+ // Sets up an intent to start the service under test
+ mStartServiceIntent = new Intent(this.getSystemContext(),AlarmService.class);
+ }
+
+ /**
+ * Cleans up the test fixture
+ * Called after each test method. If you override the method, call super.tearDown() as the
+ * last statement in your override.
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ // Always call the super constructor when overriding tearDown()
+ super.tearDown();
+ }
+
+ /**
+ * Tests the service's onCreate() method. Starts the service using startService(Intent)
+ */
+ public void testServiceCreate() {
+ // Starts the service under test
+ this.startService(mStartServiceIntent);
+
+ // Gets a handle to the service under test.
+ mService = this.getService();
+
+ // Asserts that the Notification Manager was created in the service under test.
+ assertNotNull(mService.mNotificationManager);
+
+ // Asserts that the PendingIntent for the expanded status window was created
+ assertNotNull(mService.mContentIntent);
+
+ // Asserts that the notification was created
+ assertNotNull(mService.mNotification);
+ }
+
+}