700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android电源锁和屏幕锁帮助类

Android电源锁和屏幕锁帮助类

时间:2020-11-23 10:10:23

相关推荐

Android电源锁和屏幕锁帮助类

后台常驻服务, 使用了1像素Activity保活手段:

在息屏时, 启动1像素Activity在亮屏时, 关闭1像素Activity 需要判断屏幕是否亮屏, 是否解锁. 特地写成一个帮助类. 首先AndroidMainFest中配置权限:

<!--息屏亮屏1 --><uses-permission android:name="android.permission.WAKE_LOCK"/><!--息屏亮屏2 --><uses-permission android:name="android.Manifest.permission.DEVICE_POWER"/><!--获取屏幕状态(息屏亮屏)--><uses-permission android:name="android.permission.GET_TASKS"/>

帮助类代码:

public class UPowerManager {/*** 上下文*/private Context context;/*** 回调接口*/private ScreenStatusCallback callback;/*** 电源管理*/private PowerManager pm;/*** 亮屏息屏操作对象*/private PowerManager.WakeLock wakeLock;/*** 键盘锁管理器对象*/private KeyguardManager km;/*** 屏幕监听器*/private ScreenBroadcastReceiver receiver;/*** 当前使用的电源锁类型*/private int curLevelAndFlags = -1;/*** @param context {@link Context} can not be null* @param callback {@link ScreenStatusCallback} can be null*/public UPowerManager(@NonNull Context context, @Nullable ScreenStatusCallback callback) {this.context = context;if (pm == null) {pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);}if (km == null) {km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);}//监听屏幕状态if (callback != null) {this.callback = callback;registerReceiver();}}/*** 注册屏幕监听广播*/private void registerReceiver() {if (receiver == null) {receiver = new ScreenBroadcastReceiver();}IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_USER_PRESENT);context.registerReceiver(receiver, filter);}/*** 息屏* 传递的参数可以一个, 大部分可以组合使用(使用|隔开)* 与{@link UPowerManager#setScreenOn(int)} 成对使用** @param levelAndFlags {@link PowerManager#FULL_WAKE_LOCK}* {@link PowerManager#ON_AFTER_RELEASE}* {@link PowerManager#PARTIAL_WAKE_LOCK}* {@link PowerManager#SCREEN_DIM_WAKE_LOCK}* {@link PowerManager#ACQUIRE_CAUSES_WAKEUP}* {@link PowerManager#SCREEN_BRIGHT_WAKE_LOCK}* {@link PowerManager#PROXIMITY_SCREEN_OFF_WAKE_LOCK}* {@link PowerManager#RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY}*/public void setScreenOff(int levelAndFlags) throws ArgumentNotFormatLastException {if (curLevelAndFlags != -1) {if (curLevelAndFlags != levelAndFlags) {throw new ArgumentNotFormatLastException("与上一次传递进来的参数不一致");}}curLevelAndFlags = levelAndFlags;if (wakeLock == null) {wakeLock = pm.newWakeLock(levelAndFlags, "Screen");}wakeLock.acquire();//wakeLock.acquire(2000); // 延迟2秒后获取电源锁}/*** 亮屏* 与{@link UPowerManager#setScreenOff(int)} 成对使用* 传递的参数可以一个, 大部分可以组合使用(使用|隔开)** @param levelAndFlags {@link PowerManager#FULL_WAKE_LOCK}* {@link PowerManager#ON_AFTER_RELEASE}* {@link PowerManager#PARTIAL_WAKE_LOCK}* {@link PowerManager#SCREEN_DIM_WAKE_LOCK}* {@link PowerManager#ACQUIRE_CAUSES_WAKEUP}* {@link PowerManager#SCREEN_BRIGHT_WAKE_LOCK}* {@link PowerManager#PROXIMITY_SCREEN_OFF_WAKE_LOCK}* {@link PowerManager#RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY}*/public void setScreenOn(int levelAndFlags) throws ArgumentNotFormatLastException {if (curLevelAndFlags != -1) {if (curLevelAndFlags != levelAndFlags) {throw new ArgumentNotFormatLastException("与上一次传递进来的参数不一致");}}curLevelAndFlags = levelAndFlags;if (wakeLock == null) {wakeLock = pm.newWakeLock(levelAndFlags, "Screen");}wakeLock.setReferenceCounted(false);wakeLock.release();wakeLock = null;}/*** 息屏(靠近传感器)* 与{@link UPowerManager#setScreenOn()}成对使用*/public void setScreenOff() {if (wakeLock == null) {wakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "Screen");}wakeLock.acquire();}/*** 亮屏(远离传感器)* 与{@link UPowerManager#setScreenOff()}成对使用*/public void setScreenOn() {if (wakeLock == null) {wakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "Screen");}wakeLock.setReferenceCounted(false);wakeLock.release();wakeLock = null;}/*** 释放资源: 如果传入了回调接口, 必须调用此方法解绑广播*/public void release() {if (context != null && receiver != null) {context.unregisterReceiver(receiver);}if (wakeLock != null) {wakeLock.release();wakeLock = null;}}/*** 检查屏幕状态:** @return true: 亮屏 false: 息屏*/private boolean checkScreen() {return pm.isScreenOn();}/*** 检查锁屏状态** @return true: 有锁屏, false: 无锁屏*/private boolean isScreenLock() {return km.inKeyguardRestrictedInputMode();}/*** 屏幕状态回调接口** @author tgvincent* @version 1.0*/public interface ScreenStatusCallback {/*** 亮屏*/void onScreenOn();/*** 息屏*/void onScreenOff();/*** 解锁*/void onUserPresent();}/*** 屏幕状态广播接收器** @author tgvincent* @version 1.1*/class ScreenBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();switch (action) {case Intent.ACTION_SCREEN_ON://开屏callback.onScreenOn();break;case Intent.ACTION_SCREEN_OFF://锁屏callback.onScreenOff();break;case Intent.ACTION_USER_PRESENT://解锁callback.onUserPresent();break;}}}/*** 自定义异常*/public class ArgumentNotFormatLastException extends Exception {public ArgumentNotFormatLastException(String msg) {super(msg);}}}

上述代码中的电源锁效果各不相同, 具体如下:

PowerManager.FULL_WAKE_LOCK

保持 CPU 运转, 保持屏幕高亮显示, 键盘灯也保持亮度, 受电源键影响

应用场景: 来电话, 闹钟触发等

PowerManager.ON_AFTER_RELEASE

保持 CPU 运转, 保持屏幕高亮显示, 键盘灯也保持亮度.

特别说明: 和用户体验有关, 当wakelock释放后如果没有该标志, 屏幕会立即黑屏, 如果有该标志, 屏幕会亮一小会然后在黑屏.

不能和 PowerManager.PARTIAL_WAKE_LOCK 一起用

PowerManager.PARTIAL_WAKE_LOCK:

保持 CPU 运转, 屏幕和键盘灯有可能是关闭的. 最常用,保持CPU运转, 受到电源键影响.

不能和 PowerManager.ON_AFTER_RELEASE 或者 PowerManager.ACQUIRE_CAUSES_WAKEUP 一起用

应用场景: 听音乐, 后台下载等

PowerManager.SCREEN_DIM_WAKE_LOCK:

保持 CPU 运转, 允许保持屏幕显示但有可能是灰的, 允许关闭键盘灯, 受到电源键影响

应用场景: 即将进入灭屏休眠状态时

PowerManager.ACQUIRE_CAUSES_WAKEUP:

强制使屏幕亮起, 这种锁主要针对一些必须通知用户的操作.

说明: 正常情况下, 获取wakelock是不会唤醒设备的, 加上该标志之后, acquire wakelock也会唤醒设备, 该标志常用于闹钟触发, 蓝牙链接提醒等场景.

需要设备支持距离传感器, 不能和 PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK 或 PowerManager.PARTIAL_WAKE_LOCK 一起用

PowerManager.SCREEN_BRIGHT_WAKE_LOCK:

保持CPU 运转, 允许保持屏幕高亮显示, 允许关闭键盘灯, 受到电源键影响

应用场景: 看电子书, 看视频, 操作屏幕没有操作到键盘等

PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:

与传感器有关的一个电源锁, 获取此电源锁后, 靠近传感器息屏, 远离传感器亮屏. 受电源键影响

需要设备支持距离传感器, 不能和PowerManager.ACQUIRE_CAUSES_WAKEUP一起用

PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY

另一个与传感器有关的一个电源锁, 表示当传感器判断终端离物体较远时才真正释放PROXIMITY_SCREEN_OFF_WAKE_LOCK等级的电源锁

其中:

PowerManager.FULL_WAKE_LOCK

PowerManager.SCREEN_DIM_WAKE_LOCK

PowerManager.SCREEN_BRIGHT_WAKE_LOCK

这三种类型的锁, 在6.0以后版本会逐渐被抛弃使用, 改用WindowManager. LayoutParams 的一个参数FLAG_KEEP_SCREEN_ON 来替换上述三种类型的锁,因为它将由平台被准确地管理用户应用程序之间的动作, 并且不需要特殊的权限.

示例(保持当前Activity常量):

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

注意:

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

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

以上是普通APP可以使用的电源锁, 还有一些使用注解代码@hide隐藏起来的电源锁(主要是给系统别APP使用的), 略作介绍: PowerManager.DOZE_WAKE_LOCK: 低电状态, Doze模式下, 允许cpu进入suspend状态, 系统支持Doze模式 PowerManager.DRAW_WAKE_LOCK: 保持设备唤醒, 能正常进行绘图 ... **关于屏幕锁:** 当前的屏幕锁有五种, 分别是: 没有设置屏幕锁滑动解锁图案解锁PIN码解锁密码解锁 所以下面两个方法使用时要注意:

/*** 检查屏幕状态:** @return true: 亮屏 false: 息屏*/private boolean checkScreen() {return pm.isScreenOn();}/*** 检查锁屏状态** @return true: 有锁屏, false: 无锁屏*/private boolean isScreenLock() {return km.inKeyguardRestrictedInputMode();}

如果没有设置屏幕锁, inKeyguardRestrictedInputMode() 返回值会一直为false.如果用户设置了屏幕锁(包括后四种锁中的任何一种) 屏幕不亮时返回true屏幕亮时, 解锁前返回true解锁后返回false. 有时候只需使用 inKeyguardRestrictedInputMode() 就可以了, 但当用户设置了屏幕锁的时候还需要配合isScreenOn() 方法一起使用!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。