在需要执行定时任务的类中定义如下:
Intent intent=new Intent(SimpleWakefulController.this,SimpleWakefulReceiver.class);
Pending intent=PedingIntent.getBroadcast(SimpleWakefulController.this,0,intent,0);
Calendar calendar=Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMills());
calendar.add(Calenda.Second,30);
//Schedule the alarm
AlarmManager am=(AlarmManager)getSystemService(AlARM_SERVICE);
am.set(AlarmManager.PTC_WAKEUP,calendar.getTimeINMills(),sender);
//Tell the user about what we did
if(mToast!=null)
mToast.cancel();
在Receiver类继承WakefulBroadcastReceiver中定义:
Intent service=new Intent(context,SimpleWakefulService.class);
startWakefulService(context,service);
在service类中:
onHandleIntent来处理相应的房
为了避免消耗电池,一个空闲的设备很快就会进入休眠,但是有的时候需要应用保持屏幕或CPU唤醒来完成一些工作。
实现的方法取决于你的APP的要求,一般是采取最轻量级的方法,以减少你的APP对系统资源的影响。下面讲述如何处理设备默认的休眠行为和应用需求之间的矛盾。
某些APP需要保持屏幕一直亮起,如游戏和看电影。最好的方法就是在Activity(只是Activity,而不是services或其他App的组件)中使用FLAG_KEEP_SCREEN_ON标志。例如:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
和wakelock(下面会讨论到)比较,这个方法好处就是不需要申请权限,平台就能正确地管理移动于应用之间的用户,也不需要你的APP去考虑无用资源的释放。
另一个方法去实现设备亮起就是在应用的布局文件中使用 Android:keepScreenOn属性:
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
...
使用android:keepScreenOn="true"和使用 FLAG_KEEP_SCREEN_ON是一样的,你可以选择较适合的一种。在Activity设置的好处是可以清除 FLAG_KEEP_SCREEN_ON标志,关闭屏幕。
注意:正常情况下,你是不需要清除 FLAG_KEEP_SCREEN_ON标志的,除非你不想屏幕在应用还运行时保持亮起(比如程序有一段时间都没有发生活动,你想把屏幕关闭)。当你的APP跑到后台或恢复前台时,Window manager会进行相应的设置。但是如果你想显式地进行清除这个标志,关闭屏幕,可以使用clearFlag():
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON).
有时候为了在设备休眠之前能完成一些工作,必须保持CPU运行。你可以使用一个PowerManager系统服务特性——WakeLock实现。Wakelock允许APP控制设备的电源状态。
创建并持有Wakelock对设备电池寿命有很大影响。所以你应该在确实很必要的时候才使用,且使用时间尽可能少。比如在Acitivity中就没必要用了,如前面所述,可以使用FLAG_KEEP_SCREEN_ON标志。
使用WakeLock一个合适的例子就是,当屏幕关闭的时候,后台服务中需要持有WakeLock来保持CPU运行,以继续完成工作。但还是那句话,应尽量避免WakeLock的使用,否则会影响电池寿命。
使用WakeLock的第一步就是在应用的manifest文件中添加WAKE_LOCK权限
如果你的APP包含有broadcast Receiver,且在broadcast Receiver中开启了服务去完成一些工作,那么可以通过 WakefulBroadcastReceiver来管理WakeLock,下面将会讲述,这是我们推荐的方法,如果你的APP不符合这个模式,下面是直接设置WakeLock的方法:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
调用wakelock.release()来释放WakeLock,这会释放CPU。当你的APP执行完成时不要忘了释放WakeLock,这样能避免消耗电池。
使用Broadcast Receiver和service能让你很好地管理后台任务的生命周期。
WakefulBroadcastReceiver是BroadcastReceiver的一种特例。它会为你的APP创建和管理一个PARTIAL_WAKE_LOCK 类型的WakeLock。WakefulBroadcastReceiver把工作交接给service(通常是IntentService),并保证交接过程中设备不会进入休眠状态。如果不持有WakeLock,设备很容易在任务未执行完前休眠。最终结果是你的应用不知道会在什么时候能把工作完成,相信这不是你想要的。
像其他BroadcastReceiver使用WakefulBroadcastReceiver的第一步就是把它加到manifest中:
下面的代码通过startWakefulService()开启MyIntentService,该方法和 startService()相似,不同之处在于WakefulBroadcastReceiver会在服务开启的时候持有一个WakeLock。startWakefulService传递的intent封装了WakeLock的标识符。
public class MyWakefulReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// Start the service, keeping the device awake while the service is
// launching. This is the Intent to deliver to the service.
Intent service = new Intent(context, MyIntentService.class);
startWakefulService(context, service);
}
}
当服务结束的时候,会调用 MyWakefulReceiver.completeWakefulIntent()释放WakeLock,completeWakefulIntent的参数是WakefulBroadcastReceiver传来的intent:
public class MyIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
// Do the work that requires your app to keep the CPU running.
// ...
// Release the wake lock provided by the WakefulBroadcastReceiver.
MyWakefulReceiver.completeWakefulIntent(intent);
}
}