本文主要是介绍Android官方开发文档Training系列课程中文版:管理设备的睡眠状态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原文地址:http://android.xsoftlab.net/training/scheduling/index.html
引言
当Android设备处于闲置状态时,它的屏幕首先会变暗,接着会关闭屏幕,最后会将CPU关闭。这些举措可以防止设备的电量迅速被耗尽。但是当APP需要的话,还是会有例外情况:
- 游戏类APP或者视频类APP需要保持屏幕常亮。
- 有一部分APP或许不需要屏幕保持常亮,但是它们需要CPU继续保持运转,直到它们的任务执行完毕。
这节课主要学习如何在需要的时候保持设备的唤醒状态而又不至于非常耗电。
保持设备的唤醒状态
为了避免迅速将电量耗光,Android设备会在进入闲置状态后紧接着进入睡眠状态。不过,还是有一些例外情况的:它们需要保持屏幕常亮或者是保持CPU持续运转状态以便完成某些任务。
具体采用什么样的方式这取决于APP的需求。不过,有一条规则就是尽量采取最轻量级的方法,尽可能少的消耗系统资源。
保持屏幕常亮
某些APP比如游戏类APP或者视频类APP需要保持屏幕常亮。要做到这一点只需要在Activity中使用FLAG_KEEP_SCREEN_ON就可以,不过千万不要在服务或者其它组件中使用该标志:
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);}...
}
这种方法的优势在于:它不要指定特殊权限,系统会将APP之间的状态切换处理好,也不需要担心有关释放无用资源的问题。
另一个实现方式就是在布局文件中使用android:keepScreenOn属性:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:keepScreenOn="true">...
</RelativeLayout>
android:keepScreenOn=”true”的作用效果与使用FLAG_KEEP_SCREEN_ON的效果等同。你可以选择最合适的方式。使用标志的优势在于可以动态的清除该标志的状态,以便于屏幕可以转入关闭状态。
Note: 除非可以肯定屏幕不再需要保持常亮,否则不需要我们自己专门去清除该标志。WindowManager会严格把关这些事情:APP转入后台时,APP转入前台时。但是如果你明确要清除该标志以便屏幕可以转入关闭状态,那么可以使用clearFlags():getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
保持CPU的运行
如果APP希望在系统转入睡眠状态之前完成一些事情,那么可以使用PowerManager系统服务中的WakeLock特性。WakeLock可以使APP控制设备的电源状态。
因为持有WakeLock对象可以直接与电源交互,所以只能在必要的时候使用WakeLock。绝不要在Activity中使用WakeLock。就像上面说的那样,如果希望保持屏幕常亮,只需要使用FLAG_KEEP_SCREEN_ON就可以。
使用WakeLock的合理场景就是后台服务。再强调一次,使用时应当以最小限度使用该标志,因为它会直接影响到电池的电量。
如果要使用WakeLock,首先需要在清单文件中添加WakeLock的权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
如果APP还包括了一个与服务做相关工作的广播接收器,那么可以通过WakefulBroadcastReceiver来管理WakeLock。这是一种非常理想的方案。如果APP没有那样的情况,那么也可以使用下面的方法:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag");
wakeLock.acquire();
如果要释放WakeLock,调用wakelock.release()就好。它会释放你所持有的CPU资源。在任务完成后做这项工作是很重要的,因为这可以防止电池电量被迅速耗光。
使用WakefulBroadcastReceiver
广播接收器与服务的结合使用非常易于管理后台任务的生命周期。
WakefulBroadcastReceiver是一种特殊的广播接收器:它可以创建并管理APP的PARTIAL_WAKE_LOCK。在设备即将转入睡眠状态时,WakefulBroadcastReceiver会将该信号发给服务(通常是IntentService)。如果在收到广播后没有持有WakeLock,那么可以在工作完成之前设备就会转入睡眠状态。这就会导致任务不能及时完成,这并不是我们想看到的。
WakefulBroadcastReceiver用法的第一步就是将其添加到清单文件中,与其它广播接收器的添加方式一样:
<receiver android:name=".MyWakefulReceiver"></receiver>
第二步就是使用startWakefulService()方法来启动MyIntentService。这个方法除了在启动时WakefulBroadcastReceiver持有了一个WakeLock外,其它的都与startService()很相似。在startWakefulService()中所使用的Intent被隐式的携带了一个WakeLock。
public class MyWakefulReceiver extends WakefulBroadcastReceiver {@Overridepublic 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");}@Overrideprotected 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);}
}
这篇关于Android官方开发文档Training系列课程中文版:管理设备的睡眠状态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!