Sample app and test package for a Service
Change-Id: I6589a1b761f5c40b86f1319c30ead2409113b647
This commit is contained in:
@@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
216
samples/Alarm/src/com/example/android/newalarm/AlarmService.java
Normal file
216
samples/Alarm/src/com/example/android/newalarm/AlarmService.java
Normal file
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user