性能优化-屏幕常亮与CPU唤醒

时间:2022-10-22 16:26:36

Android在不使用的时候,屏幕在一段时间以后会变暗,再过一段时间就会熄屏,此时CPU就会休眠,那么在这个时候,Timer、Handler、Thread、Service等都会暂停,有时候我们需要屏幕常亮,有时候需要熄屏后CPU仍然运作,那么这就是本文记录的主题

保持屏幕常亮

最好的方式是在Activity中使用FLAG_KEEP_SCREEN_ON的Flag

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);
}
}

这个方法的好处是不像唤醒锁(wake locks),需要一些特定的权限(permission)。并且能正确管理不同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一样。使用代码的好处是你允许你在需要的地方关闭屏幕

注意:一般不需要人为的去掉FLAG_KEEP_SCREEN_ON的flag,windowManager会管理好程序进入后台回到前台的的操作。如果确实需要手动清掉常亮的flag,使用getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

保持CPU运行

需要使用PowerManager这个系统服务的唤醒锁(wake locks)特征来保持CPU处于唤醒状态。唤醒锁允许程序控制宿主设备的电量状态。创建和持有唤醒锁对电池的续航有较大的影响,所以,除非是真的需要唤醒锁完成尽可能短的时间在后台完成的任务时才使用它。比如在Acitivity中就没必要用了。如果需要关闭屏幕,使用上述的FLAG_KEEP_SCREEN_ON

只有一种合理的使用场景,是在使用后台服务在屏幕关闭情况下hold住CPU完成一些工作。 要使用唤醒锁,如果不使用唤醒锁来执行后台服务,不能保证因CPU休眠未来的某个时刻任务会停止,这不是我们想要的 (有的人可能认为我以前写的后台服务就没掉过链子呀运行得挺好的,1.可能是你的任务时间比较短;2.可能CPU被手机里面很多其他的软件一直在唤醒状态)

唤醒锁可划分为并识别四种用户唤醒锁

标记值 CPU 屏幕 键盘
PARTIAL_WAKE_LOCK 开启 关闭 关闭
SCREEN_DIM_WAKE_LOCK 开启 变暗 关闭
SCREEN_BRIGHT_WAKE_LOCK 开启 变亮 关闭
FULL_WAKE_LOCK 开启 变亮 变亮

API等级17开始,FULL_WAKE_LOCK将被弃用。 应用应使用FLAG_KEEP_SCREEN_ON

第一步就是添加唤醒锁权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />
  • 直接使用唤醒锁:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag");
wakeLock.acquire();

注意:在使用该类的时候,必须保证acquirerelease是成对出现的

  • 但推荐的方式是使用WakefulBroadcastReceiver使用广播和Service(典型的IntentService)结合的方式可以让你很好地管理后台服务的生命周期

    WakefulBroadcastReceiverBroadcastReceiver的一种特例。它会为你的APP创建和管理一个PARTIAL_WAKE_LOCK类型的WakeLockWakefulBroadcastReceiver把工作交接给service(通常是IntentService),并保证交接过程中设备不会进入休眠状态。如果不持有WakeLock,设备很容易在任务未执行完前休眠。最终结果是你的应用不知道会在什么时候能把工作完成,相信这不是你想要的

    使用WakefulBroadcastReceiver第一步就是在Manifest中注册
<receiver android:name=".MyWakefulReceiver" />

使用startWakefulService()方法来启动服务,与startService()相比,在启动服务的同时,并启用了唤醒锁

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()来释放唤醒锁

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);
}
}

采用定时重复的Service开启

  • 利用Android自带的定时器AlarmManager实现
Intent intent = new Intent(mContext, ServiceTest.class);
PendingIntent pi = PendingIntent.getService(mContext, 1, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Service.ALARM_SERVICE);
if(alarm != null) {
alarm.cancel(pi);
// 闹钟在系统睡眠状态下会唤醒系统并执行提示功能
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000, 2000, pi);
// 确切的时间闹钟alarm.setExact(…);
//alarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
}
  • 该定时器可以启动Service服务发送广播跳转Activity,并且会在系统睡眠状态下唤醒系统。所以该方法不用获取电源锁和释放电源锁

    注:在19以上版本,setRepeating中设置的频繁只是建议值(6.0的源码中最小值是60s),如果要精确一些的用setWindow或者setExact

首先Android手机有两个处理器,一个叫Application Processor(AP),一个叫Baseband Processor(BP)。AP是ARM架构的处理器,用于运行Linux+Android系统;BP用于运行实时操作系统(RTOS),通讯协议栈运行于BP的RTOS之上。非通话时间,BP的能耗基本上在5mA左右,而AP只要处于非休眠状态,能耗至少在50mA以上,执行图形运算时会更高。另外LCD工作时功耗在100mA左右,WIFI也在100mA左右。一般手机待机时,AP、LCD、WIFI均进入休眠状态,这时Android中应用程序的代码也会停止执行

Android为了确保应用程序中关键代码的正确执行,提供了Wake Lock的API,使得应用程序有权限通过代码阻止AP进入休眠状态。但如果不领会Android设计者的意图而滥用Wake Lock API,为了自身程序在后台的正常工作而长时间阻止AP进入休眠状态,就会成为待机电池杀手。比如前段时间的某应用,比如现在仍然干着这事的某应用

那么Wake Lock API有啥用呢?比如心跳包从请求到应答,比如断线重连重新登陆这些关键逻辑的执行过程,就需要Wake Lock来保护。而一旦一个关键逻辑执行成功,就应该立即释放掉Wake Lock了。两次心跳请求间隔5到10分钟,基本不会怎么耗电。除非网络不稳定,频繁断线重连,那种情况办法不多

AlarmManagerAndroid系统封装的用于管理RTC的模块,RTC(Real Time Clock)是一个独立的硬件时钟,可以在CPU休眠时正常运行,在预设的时间到达时,通过中断唤醒CPU(极光推送就是利用这个来做的)

总结:

1.关键逻辑的执行过程,就需要Wake Lock来保护。如断线重连重新登陆

2.休眠的情况下如何唤醒来执行任务?用AlarmManager。如推送消息的获取

注:如果请求网络很差,会要很长的时间,一般我们谷歌建议一定要设置请求超时时间

性能优化-屏幕常亮与CPU唤醒的更多相关文章

  1. LongLightUtils【保持屏幕常亮工具类】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这里只是简单记录下保持屏幕常亮工具类LongLightUtils的使用,具体请阅读参考资料<Android屏幕常亮,其实很简单 ...

  2. cocos2d-x 如何保持屏幕常亮

    转自:http://blog.csdn.net/wolfking_2009/article/details/8939027 貌似cocos2d-x没有接口直接做这个功能 而各个平台又不一样,所以只能对 ...

  3. win10 uwp 屏幕常亮

    我们在播放视频需要屏幕常亮,我们可以使用DisplayRequest,因为代码简单我直接写,代码来自https://msdn.microsoft.com/en-us/library/windows/a ...

  4. Xamarin Essentials教程屏幕常亮ScreenLock

    Xamarin Essentials教程屏幕常亮ScreenLock   在一段时间内,如果用户没有对设备进行操作,设备就会自动关闭屏幕.用户必须手动操作,才能点亮屏幕.但是很多应用需要在用户没有操作 ...

  5. 完美实现Android的屏幕常亮功能

    笔者所在公司做的APP是股票类的,用户在查看股票报价页面的时候,往往需要开启盯盘模式,这个时候屏幕是不能黑屏的,黑屏会导致用户看不到一些关键报价涨跌,错过了买入卖出的最佳时机,就会给用户造成损失,这是 ...

  6. Android保持屏幕常亮

    Android保持屏幕常亮,PowerManager.WakeLock的使用 package com.hebaijun.wakelock;      import android.app.Activi ...

  7. Android保持屏幕常亮唤醒状态

    第一步:  首先添加权限: <uses-permission android:name="android.permission.WAKE_LOCK"></uses ...

  8. Android保持屏幕常亮的方法

    以前一直使用newWakeLock方法: this.powerManager = (PowerManager) this .getSystemService(Context.POWER_SERVICE ...

  9. 《Android应用性能优化》2——内存、CPU、性能测评

    4.高效使用内存 4.1 说说内存 Android设备的性能主要取决于以下三因素: CPU如何操纵特定的数据类型: 数据和指令需占用多少存储空间: 数据在内存中的布局 4.2 数据类型 int和lon ...

随机推荐

  1. TC250专场

    SRM 623 DIV2 1000pt 题意:给出一个最多50*50的矩阵,每个单元可能为'.'.'P'.'A','.'代表空地,你每次操作可以把一个P或者A拿到空地上,求一个最大的含有相同字符的矩形 ...

  2. Window对象

    Window对象:         Window 对象表示浏览器中打开的窗口,如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框 ...

  3. Django 一对多,多对多关系解析

    [转]Django 一对多,多对多关系解析   Django 的 ORM 有多种关系:一对一,多对一,多对多. 各自定义的方式为 :        一对一: OneToOneField         ...

  4. 『TCP&sol;IP详解——卷一:协议』读书笔记——09

    2013-08-22 12:42:26 3.4 子网寻址 子网编码:不是把IP地址看成由单纯的网络号和主机号组成,我们把主机号再分成子网号和主机号.这样做是因为,A.B类地址为主机号分配了太多的空间, ...

  5. BI项目需求分析书-模板

    目录 目录 .............................................................................................. ...

  6. 原型 prototype

    原型 prototype js 的对象比较 由于 js 是解释执行的语言, 那么再代码中出现函数与对象如果重复执行, 会创建多个副本 在代码中重复执行的代码容易出现重复的对象 创建一个 Person ...

  7. Spring Resource之ResourceLoader

    ResourceLoader接口意味着任何实现的对象都能够返回Resource实例. public interface ResourceLoader { Resource getResource(St ...

  8. ACM课程总结

    当我还是一个被P哥哥忽悠来的无知少年时,以为编程只有C语言那么点东西,半个学期学完C语言的我以为天下无敌了,谁知自从有了杭电练习题之后,才发现自己简直就是渣渣--咳咳进入正题: STL篇: 成长为一名 ...

  9. mysql 5&period;7~默认sql&lowbar;mode解读

    当5.6升级到5.7时,首先要注意的就是sql_mode对业务的影响 大概可以分为几类1 共同支持,如果你的5.6和5.7sql_mode配置支持的交集一样,那么不用考虑2 5.7细说  1 ONLY ...

  10. &lbrack;转帖&rsqb; SQL参数化的优点 CopyFrom https&colon;&sol;&sol;www&period;cnblogs&period;com&sol;-lzb&sol;articles&sol;4840671&period;html

    梦在远方的小猪 感谢原作者...  后面总结的五点感觉挺好的.. 自己之前的知识点一直没有串起来. 转帖记录一下感谢. sql参数化参数化 说来惭愧,工作差不多4年了,直到前些日子被DBA找上门让我优 ...