android in practice_Using the AlarmManager(portfolio project)

system-level alarms.
you can’t guarantee that it’ll still be running at that point in the future.
To ensure that our code is executed at the desired time, we can’t rely on the Service because the OS could kill the Service to free up memory. We must use the OS to schedule the execution, and to do this we must use the android.app.AlarmManager class.
we’ve already created a BroadcastReceiver that’s invoked when the device finishes booting up.here you see a new version that instead schedules the Service to be executed.
Using a device boot receiver to schedule Service execution.
modify the  device boot  BroadcastReceiver   class PortfolioStartupReceiver:
/**
 * <code>BroadcastReceiver</code> that is notified when the device boots up.
 * It uses the {AlarmManager} to schedule regular invocations of the {@PortfolioManagerService}.
 * 
 * This can be easily modified to use Cloud to Device Messaging, see comments in the code for details.
 * 
 */
public class PortfolioStartupReceiver extends BroadcastReceiver {
	private static final int FIFTEEN_MINUTES = 15*60*1000;
	// Uncomment this constant to use C2DM and insert the email address that
	// you use to submit your apps to the Android Market
	//private static final String DEVELOPER_EMAIL_ADDRESS = "";
	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		/*It creates a new Intent and uses that Intent to start the Service.
		 * This will cause the onCreate and then the onStartCommand methods to be invoked on our Service(PortfolioManagerService), 
		 * and then return back to the BroadcastReceiver.
		 */
		//start the background service once the device boots up.
		//Intent stockService=new Intent(context,PortfolioManagerService.class);
		//context.startService(stockService);
		
		// Begin AlarmManager code. Delete this to use C2DM
		AlarmManager mgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
		Intent i=new Intent(context,AlarmReceiver.class);
		PendingIntent sender=PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
		Calendar now=Calendar.getInstance();
		now.add(Calendar.MINUTE,2);
		mgr.setRepeating(AlarmManager.RTC_WAKEUP, now.getTimeInMillis(), FIFTEEN_MINUTES, sender);
		// End AlarmManager code
		
		// Uncomment out the following code to use C2DM
//		Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
//		registrationIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0)); // boilerplate
//		registrationIntent.putExtra("sender", DEVELOPER_EMAIL_ADDRESS);
//		context.startService(registrationIntent);
		
	}
}
we’ve changed the implementation of the onReceive method. Now instead of starting the Service, we’ll schedule it. We create an Intent B for the BroadcastReceiver that will receive the alarm from the AlarmManager.
we use the AlarmManager C to schedule the PendingIntent for execution. By specifying the type of alarm as RTC_WAKEUP, we’re instructing the OS to execute this alarm even if the device has been put to sleep.
Note that our Intent wasn’t for the Service directly,but instead for a class called AlarmReceiver. 
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
	Intent stockService =new Intent(context, PortfolioManagerService.class);
	context.startService(stockService);
	}
}
All it does is create an Intent for the PortfolioManagerService and then immediately start that Service.
now we want that Service to update the stock data and check whether it needs to send Notifications to the user.

Modified Service to work with system alarms:

public class PortfolioManagerService extends Service {
// other code omitted
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	updateStockData();
	return Service.START_NOT_STICKY;
	}
}
To get our Service to work properly with the system alarms, we need to override another of android.app.Service’s lifecycle methods: the onStartCommand method.
This method will be invoked each time a client context calls startService, such as in listing 5.18, even if the Service is already running. All we want to do is call our update-
StockData method, since it’ll take care of retrieving fresh data from the network,updating the locally cached data in our database, checking whether we need to send out Notifications, and send them out if so.
Note that this method must return an integer. The value of that integer tells the OS what to do with the Service if it’s killed by the OS. The START_NOT_STICKY flag indicates that the OS can forget about this Service if it has to kill it.
SERVICE ONSTART VERSUS ONSTARTCOMMAND,You should always use onStartCommand, unless you need to write code specifically for devices running pre-2.0.


你可能感兴趣的:(android in practice_Using the AlarmManager(portfolio project))