当前位置:   article > 正文

android app设置亮屏的几种方式以及功耗对比_setturnscreenon

setturnscreenon

Android app开发中,为了让某个页面持续显示一定时间,需要设置亮屏代码。

常用的方法有四种,分别如下:

方法1:通过PowerManager获取wakelock。

方法2:在view中设置view.setKeepScreenOn(true);

方法3:设置WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 和 setTurnScreenOn(true);

方法4:在xml中设置android:keepScreenOn="true"

下面说一下上面四种方法的对比:

方法1一般用在非activity、fragment,无法操作UI界面的服务,如service、receiver。

需要申请权限

  1. <uses-permission android:name="android.permission.WAKE_LOCK" />  
  1. PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
  2. PowerManager.WakeLock wakeLock = pm.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK
  3. | PowerManager.ACQUIRE_CAUSES_WAKEUP), "reminder:");
  4. //wakeLock.setReferenceCounted(false);
  5. wakeLock.acquire(6000L);

wakelock.acquire()不带参数的不建议使用,建议使用带参数的,带参数的系统会自动release,是比较安全的,即便是手动release后被系统handler自动释放,也不会出现crash。因为PowerManager有两个计数值,mInternalCount和mExternalCount,系统自动释放时不会操作mExternalCount。

  1. public void release(int flags) {
  2. synchronized (mToken) {
  3. if (mInternalCount > 0) {
  4. // internal count must only be decreased if it is > 0 or state of
  5. // the WakeLock object is broken.
  6. mInternalCount--;
  7. }
  8. if ((flags & RELEASE_FLAG_TIMEOUT) == 0) {
  9. mExternalCount--;
  10. }
  11. if (!mRefCounted || mInternalCount == 0) {
  12. mHandler.removeCallbacks(mReleaser);
  13. if (mHeld) {
  14. Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
  15. try {
  16. mService.releaseWakeLock(mToken, flags);
  17. } catch (RemoteException e) {
  18. throw e.rethrowFromSystemServer();
  19. }
  20. mHeld = false;
  21. }
  22. }
  23. if (mRefCounted && mExternalCount < 0) {
  24. throw new RuntimeException("WakeLock under-locked " + mTag);
  25. }
  26. }
  27. }

但如果应用层手动执行release比acquire要多,且没有设置mRefCounted为true,系统就会抛异常。

其中wakeLock.setReferenceCounted(false);的作用是无论调用多少次acquire,只要最后执行了一次release就会释放wakelock,该值默认为true;

  1. WakeLock获取时相关的flag如下所示:
  2. PARTIAL_WAKE_LOCK :保持CPU 运转,屏幕和键盘灯有可能是关闭的。
  3. SCREEN_DIM_WAKE_LOCK :保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
  4. SCREEN_BRIGHT_WAKE_LOCK :保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
  5. FULL_WAKE_LOCK :保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
  6. ————————————————
  7. 版权声明:本文为CSDN博主「llljjlj」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
  8. 原文链接:https://blog.csdn.net/llljjlj/article/details/80631664

在含有UI界面的activity、fragment中不推荐使用pm wakelock,推荐使用方法2和3。

  1. @RequiresApi(api = Build.VERSION_CODES.O_MR1)
  2. private void clearKeepScreenOnFlag() {
  3. Activity activity = getActivity();
  4. if (activity != null) {
  5. activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  6. activity.setTurnScreenOn(false);
  7. }
  8. }
  9. @RequiresApi(api = Build.VERSION_CODES.O_MR1)
  10. private void setKeepScreenOnFlag() {
  11. Activity activity = getActivity();
  12. if (activity != null) {
  13. activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  14. activity.setTurnScreenOn(true);
  15. }
  16. }
  17. 或者
  18. @Nullable
  19. @Override
  20. public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  21. fragmentLayoutRoot=inflater.inflate(R.layout.fragment_dobreath_prepare, container, false);
  22. fragmentLayoutRoot.setKeepScreenOn(true);
  23. mHandler.postDelayed(mCleanKeepScreenTask,120*1000);
  24. return fragmentLayoutRoot;
  25. }

 下面分析三种方式的功耗分析:

执行方法1.查看dumpsys power信息。

  1. private void wakeLockPm(Context context) {
  2. PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
  3. PowerManager.WakeLock wakeLock = pm.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK
  4. | PowerManager.ACQUIRE_CAUSES_WAKEUP), "reminder:");
  5. //wakeLock.setReferenceCounted(false);
  6. wakeLock.acquire(6000L);
  7. }
  8. $ adb shell dumpsys power | grep -i wake
  9. no_cached_wake_locks=true
  10. mWakefulness=Awake
  11. mWakefulnessChanging=false
  12. mWakeLockSummary=0x23
  13. mLastWakeTime=4321190 (82051 ms ago)
  14. mHoldingWakeLockSuspendBlocker=true
  15. mWakeUpWhenPluggedOrUnpluggedConfig=true
  16. mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  17. mDrawWakeLockOverrideFromSidekick=false
  18. mDoubleTapWakeEnabled=false
  19. Wake Locks: size=1
  20. SCREEN_BRIGHT_WAKE_LOCK 'reminder:' ACQUIRE_CAUSES_WAKEUP ACQ=-1s927ms (uid=10054 pid=8081)
  21. PowerManagerService.WakeLocks: ref count=1
  22. mGravitySensor={Sensor name="gravity Non-wakeup", vendor="qualcomm", version=1, type=9, maxRange=1.0, resolution=0.1, power=0.515, minDelay=20000}
  23. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  24. $ adb shell dumpsys power | grep -i screen
  25. mLastScreenBrightnessBoostTime=0 (4406128 ms ago)
  26. mScreenBrightnessBoostInProgress=false
  27. mSuspendWhenScreenOffDueToProximityConfig=true
  28. mDozeAfterScreenOff=false
  29. mMinimumScreenOffTimeoutConfig=5000
  30. mMaximumScreenDimDurationConfig=1000
  31. mMaximumScreenDimRatioConfig=0.20000005
  32. mScreenOffTimeoutSetting=30000
  33. mMaximumScreenOffTimeoutFromDeviceAdmin=9223372036854775807 (enforced=false)
  34. mScreenBrightnessSetting=0
  35. mScreenBrightnessModeSetting=1
  36. mScreenBrightnessOverrideFromWindowManager=-1
  37. mDozeScreenStateOverrideFromDreamManager=0
  38. mDozeScreenBrightnessOverrideFromDreamManager=-1
  39. mScreenBrightnessSettingMinimum=10
  40. mScreenBrightnessSettingMaximum=254
  41. mScreenBrightnessSettingDefault=208
  42. Screen off timeout: 30000 ms
  43. Screen dim duration: 1000 ms
  44. SCREEN_BRIGHT_WAKE_LOCK 'reminder:' ACQUIRE_CAUSES_WAKEUP ACQ=-4s813ms (uid=10054 pid=8081)

上面设置的是wakelock 6秒后自动释放,释放后再看信息

  1. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  2. $ adb shell dumpsys power | grep -i wake
  3. no_cached_wake_locks=true
  4. mWakefulness=Asleep
  5. mWakefulnessChanging=false
  6. mWakeLockSummary=0x0
  7. mLastWakeTime=4321190 (177007 ms ago)
  8. mHoldingWakeLockSuspendBlocker=false
  9. mWakeUpWhenPluggedOrUnpluggedConfig=true
  10. mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  11. mDrawWakeLockOverrideFromSidekick=false
  12. mDoubleTapWakeEnabled=false
  13. Wake Locks: size=0
  14. PowerManagerService.WakeLocks: ref count=0
  15. mGravitySensor={Sensor name="gravity Non-wakeup", vendor="qualcomm", version=1, type=9, maxRange=1.0, resolution=0.1, power=0.515, minDelay=20000}
  16. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  17. $ adb shell dumpsys power | grep -i screen
  18. mLastScreenBrightnessBoostTime=0 (4501875 ms ago)
  19. mScreenBrightnessBoostInProgress=false
  20. mSuspendWhenScreenOffDueToProximityConfig=true
  21. mDozeAfterScreenOff=false
  22. mMinimumScreenOffTimeoutConfig=5000
  23. mMaximumScreenDimDurationConfig=1000
  24. mMaximumScreenDimRatioConfig=0.20000005
  25. mScreenOffTimeoutSetting=30000
  26. mMaximumScreenOffTimeoutFromDeviceAdmin=9223372036854775807 (enforced=false)
  27. mScreenBrightnessSetting=0
  28. mScreenBrightnessModeSetting=1
  29. mScreenBrightnessOverrideFromWindowManager=-1
  30. mDozeScreenStateOverrideFromDreamManager=0
  31. mDozeScreenBrightnessOverrideFromDreamManager=-1
  32. mScreenBrightnessSettingMinimum=10
  33. mScreenBrightnessSettingMaximum=254
  34. mScreenBrightnessSettingDefault=208
  35. Screen off timeout: 5000 ms
  36. Screen dim duration: 1000 ms

使用wakelock可以加tag,方便功耗分析定位问题。

使用该方法的风险在于,必须有正确配对的release方式才不会功耗异常,若没有地方释放就会一直亮屏耗电。如果是在activity中使用,即便是activity 页面pause了,也不会自动release,所以应该尽量避免使用walock的方式。

  1. fragmentLayout.setKeepScreenOn(true);
  2. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  3. $ adb shell dumpsys power | grep -i screen
  4. mLastScreenBrightnessBoostTime=0 (5352101 ms ago)
  5. mScreenBrightnessBoostInProgress=false
  6. mSuspendWhenScreenOffDueToProximityConfig=true
  7. mDozeAfterScreenOff=false
  8. mMinimumScreenOffTimeoutConfig=5000
  9. mMaximumScreenDimDurationConfig=1000
  10. mMaximumScreenDimRatioConfig=0.20000005
  11. mScreenOffTimeoutSetting=30000
  12. mMaximumScreenOffTimeoutFromDeviceAdmin=9223372036854775807 (enforced=false)
  13. mScreenBrightnessSetting=0
  14. mScreenBrightnessModeSetting=1
  15. mScreenBrightnessOverrideFromWindowManager=-1
  16. mDozeScreenStateOverrideFromDreamManager=0
  17. mDozeScreenBrightnessOverrideFromDreamManager=-1
  18. mScreenBrightnessSettingMinimum=10
  19. mScreenBrightnessSettingMaximum=254
  20. mScreenBrightnessSettingDefault=208
  21. Screen off timeout: 30000 ms
  22. Screen dim duration: 1000 ms
  23. SCREEN_BRIGHT_WAKE_LOCK 'WindowManager' ON_AFTER_RELEASE ACQ=-23s285ms (uid=1000 pid=1400 ws=WorkSource{10054})
  24. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  25. $ adb shell dumpsys power | grep -i wake
  26. no_cached_wake_locks=true
  27. mWakefulness=Awake
  28. mWakefulnessChanging=false
  29. mWakeLockSummary=0x23
  30. mLastWakeTime=5285832 (69745 ms ago)
  31. mHoldingWakeLockSuspendBlocker=true
  32. mWakeUpWhenPluggedOrUnpluggedConfig=true
  33. mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  34. mDrawWakeLockOverrideFromSidekick=false
  35. mDoubleTapWakeEnabled=false
  36. Wake Locks: size=1
  37. SCREEN_BRIGHT_WAKE_LOCK 'WindowManager' ON_AFTER_RELEASE ACQ=-26s761ms (uid=1000 pid=1400 ws=WorkSource{10054})
  38. PowerManagerService.WakeLocks: ref count=1
  39. mGravitySensor={Sensor name="gravity Non-wakeup", vendor="qualcomm", version=1, type=9, maxRange=1.0, resolution=0.1, power=0.515, minDelay=20000}

执行view.setkeepScreenon(true)不受抬腕影响。view pause或destroy时,会自动释放SCREEN_BRIGHT_WAKE_LOCK,推荐使用这种方式。

方法3:

  1. 在activity中执行
  2. getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  3. setTurnScreenOn(true);
  4. $ adb shell dumpsys power | grep -i wake
  5. no_cached_wake_locks=true
  6. mWakefulness=Awake
  7. mWakefulnessChanging=false
  8. mWakeLockSummary=0x23
  9. mLastWakeTime=5636910 (28381 ms ago)
  10. mHoldingWakeLockSuspendBlocker=true
  11. mWakeUpWhenPluggedOrUnpluggedConfig=true
  12. mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  13. mDrawWakeLockOverrideFromSidekick=false
  14. mDoubleTapWakeEnabled=false
  15. Wake Locks: size=1
  16. SCREEN_BRIGHT_WAKE_LOCK 'WindowManager' ON_AFTER_RELEASE ACQ=-22s316ms (uid=1000 pid=1400 ws=WorkSource{10054})
  17. PowerManagerService.WakeLocks: ref count=1
  18. mGravitySensor={Sensor name="gravity Non-wakeup", vendor="qualcomm", version=1, type=9, maxRange=1.0, resolution=0.1, power=0.515, minDelay=20000}
  19. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  20. $ adb shell dumpsys power | grep -i screen
  21. mLastScreenBrightnessBoostTime=0 (5670577 ms ago)
  22. mScreenBrightnessBoostInProgress=false
  23. mSuspendWhenScreenOffDueToProximityConfig=true
  24. mDozeAfterScreenOff=false
  25. mMinimumScreenOffTimeoutConfig=5000
  26. mMaximumScreenDimDurationConfig=1000
  27. mMaximumScreenDimRatioConfig=0.20000005
  28. mScreenOffTimeoutSetting=30000
  29. mMaximumScreenOffTimeoutFromDeviceAdmin=9223372036854775807 (enforced=false)
  30. mScreenBrightnessSetting=0
  31. mScreenBrightnessModeSetting=1
  32. mScreenBrightnessOverrideFromWindowManager=-1
  33. mDozeScreenStateOverrideFromDreamManager=0
  34. mDozeScreenBrightnessOverrideFromDreamManager=-1
  35. mScreenBrightnessSettingMinimum=10
  36. mScreenBrightnessSettingMaximum=254
  37. mScreenBrightnessSettingDefault=208
  38. Screen off timeout: 30000 ms
  39. Screen dim duration: 1000 ms
  40. SCREEN_BRIGHT_WAKE_LOCK 'WindowManager' ON_AFTER_RELEASE ACQ=-27s602ms (uid=1000 pid=1400 ws=WorkSource{10054})

效果与方法2相同,activity pause后自动释放,再次resume自动screen_bright_wake_lock。

为了避免用户误操作到该页面长时间亮屏耗电,建议加入超时释放逻辑。

方法4:

  1. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:app="http://schemas.android.com/apk/res-auto"
  3. android:keepScreenOn="true"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content">
  6. </android.support.constraint.ConstraintLayout>
  7. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  8. $ adb shell dumpsys power | grep -i wake
  9. no_cached_wake_locks=true
  10. mWakefulness=Awake
  11. mWakefulnessChanging=false
  12. mWakeLockSummary=0x23
  13. mLastWakeTime=5733001 (174149 ms ago)
  14. mHoldingWakeLockSuspendBlocker=true
  15. mWakeUpWhenPluggedOrUnpluggedConfig=true
  16. mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  17. mDrawWakeLockOverrideFromSidekick=false
  18. mDoubleTapWakeEnabled=false
  19. Wake Locks: size=1
  20. SCREEN_BRIGHT_WAKE_LOCK 'WindowManager' ON_AFTER_RELEASE ACQ=-8s160ms (uid=1000 pid=1400 ws=WorkSource{10054})
  21. PowerManagerService.WakeLocks: ref count=1
  22. mGravitySensor={Sensor name="gravity Non-wakeup", vendor="qualcomm", version=1, type=9, maxRange=1.0, resolution=0.1, power=0.515, minDelay=20000}
  23. lingx@MI-20170703YUWL MINGW64 /e/watch/Apps/fitness (master)
  24. $ adb shell dumpsys power | grep -i screen
  25. mLastScreenBrightnessBoostTime=0 (5909168 ms ago)
  26. mScreenBrightnessBoostInProgress=false
  27. mSuspendWhenScreenOffDueToProximityConfig=true
  28. mDozeAfterScreenOff=false
  29. mMinimumScreenOffTimeoutConfig=5000
  30. mMaximumScreenDimDurationConfig=1000
  31. mMaximumScreenDimRatioConfig=0.20000005
  32. mScreenOffTimeoutSetting=30000
  33. mMaximumScreenOffTimeoutFromDeviceAdmin=9223372036854775807 (enforced=false)
  34. mScreenBrightnessSetting=0
  35. mScreenBrightnessModeSetting=1
  36. mScreenBrightnessOverrideFromWindowManager=-1
  37. mDozeScreenStateOverrideFromDreamManager=0
  38. mDozeScreenBrightnessOverrideFromDreamManager=-1
  39. mScreenBrightnessSettingMinimum=10
  40. mScreenBrightnessSettingMaximum=254
  41. mScreenBrightnessSettingDefault=208
  42. Screen off timeout: 30000 ms
  43. Screen dim duration: 1000 ms
  44. SCREEN_BRIGHT_WAKE_LOCK 'WindowManager' ON_AFTER_RELEASE ACQ=-10s177ms (uid=1000 pid=1400 ws=WorkSource{10054})

从现象看与方法2、3效果相同。但实际使用有很大区别,因为在xml中设置了keepScreenOn=true,在代码中执行getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

setTurnScreenOn(false);

后发现SCREEN_BRIGHT_WAKE_LOCK并未释放。因此只有当确定本页面显示时不会被息屏才能在xml中配置亮屏,例如一个闪屏页面,过度页面,这些页面一般持续时间不能太长。

综上所述:

1. 如果是在receiver、broadcast中亮屏、唤醒cpu,只能使用wakelock,建议使用wakelock.acquire(xxxx)带参数的。

必须有地方释放wakelock,否则会持续亮屏、cpu活跃会对功耗有较大影响。

2. 如果是在activity、fragment等包含view 资源的页面中亮屏,建议使用方法2、3,设置view.setKeepScreenOn(true);

或者设置WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 和 setTurnScreenOn(true);

3.如果是闪现过度页面,可以使用方法4在xml中配置keepScreenOn=true,因为这类页面持续时间短,也不需要考虑自动释放机制。

方法234所显示的页面,只要页面退到后台后都会自动释放SCREEN_BRIGHT_WAKE_LOCK。所以在包含view的页面中,尽量避免方法1。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/888994
推荐阅读
相关标签
  

闽ICP备14008679号