Android官方开发文档Training系列课程中文版:管理设备的睡眠状态

简介: 原文地址:http://android.xsoftlab.net/training/scheduling/index.html引言当Android设备处于闲置状态时,它的屏幕首先会变暗,接着会关闭屏幕,最后会将CPU关闭。

原文地址: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 {
  @Override
  protected 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 {
    @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);
    }
}
目录
相关文章
|
9月前
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
399 64
|
9月前
|
存储 Android开发 数据安全/隐私保护
如何在Android设备上撤销Flutter应用程序的所有权限?
如何在Android设备上撤销Flutter应用程序的所有权限?
525 64
|
9月前
|
缓存 Android开发 开发者
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
Flutter环境配置完成后,如何在Android设备上运行Flutter应用程序?
1622 62
|
9月前
|
开发工具 Android开发 开发者
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
在Android设备上运行Flutter应用程序时,如果遇到设备未授权的问题该如何解决?
558 61
|
10月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
本文介绍了如何在基于Amlogic T972的Android 9.0系统上使用Platform平台驱动框架和设备树(DTS),实现设备与驱动的分离,并通过静态枚举在设备树中描述设备,自动触发驱动程序的加载和设备创建。
373 0
基于Amlogic 安卓9.0, 驱动简说(四):Platform平台驱动,驱动与设备的分离
|
Android开发 C语言
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
这篇文章是关于如何在基于Amlogic T972的Android 9.0系统上,通过自动分配设备号和自动创建设备节点文件的方式,开发字符设备驱动程序的教程。
294 0
基于Amlogic 安卓9.0, 驱动简说(二):字符设备驱动,自动创建设备
|
自然语言处理 Shell Linux
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
本文是关于在Amlogic安卓9.0平台上创建字符设备驱动的教程,详细介绍了驱动程序的编写、编译、部署和测试过程,并提供了完整的源码和应用层调用示例。
397 0
基于Amlogic 安卓9.0, 驱动简说(一):字符设备驱动,手动创建设备
|
传感器 Android开发 芯片
不写一行代码(三):实现安卓基于i2c bus的Slaver设备驱动
本文是系列文章的第三篇,展示了如何在Android系统中利用现有的i2c bus驱动,通过编写设备树节点和应用层的控制代码,实现对基于i2c bus的Slaver设备(如六轴陀螺仪模块QMI8658C)的控制,而无需编写设备驱动代码。
477 0
不写一行代码(三):实现安卓基于i2c bus的Slaver设备驱动
|
Android开发
不写一行代码(二):实现安卓基于PWM的LED设备驱动
本文介绍了在Android系统中不编写任何代码,通过设备树配置和内核支持的通用PWM LED驱动来实现基于PWM的LED设备驱动,并通过测试命令调整LED亮度级别。
447 0
不写一行代码(二):实现安卓基于PWM的LED设备驱动