安卓如何实现双击触摸唤醒点亮屏幕功能-Android framework实战开发

背景

经常有学员朋友在群里问到一个目前市场上常见的功能:
手机待机时候双击屏幕可以唤醒点亮手机屏幕功能
如何实现这个功能,经常有同学在群里求助,今天就刚好来讨论一下这个待机时候双击触摸唤醒点亮屏幕的功能的实现方案。

在这里插入图片描述

功能核心方案设计:

正常息屏待机时候,通过getevent是无法获取到任何的触摸事件,因为这个时候触摸屏驱动是没有工作,不会上报,需要息屏时候实现实现对触摸事件的输入,那么就需要考虑如何在息屏时候让触摸运行起来,这里一般可能会想到如下2个方案:

方案1、整体的息屏就是个假息屏,即息屏其实本质就是让背光关闭,但是触摸和画面等是可以正常使用,即这个息屏待机其实仅仅是背光关闭而已,但是系统app,触摸等都是正常运行的,只是没有背光看着屏幕息屏而已,这种其实整体功耗相比原来的息屏就会大很多。

方案2、息屏是正常的息屏,整体app画面也进入待机模式,不会在绘制画面等,背光也是关闭的,但是触摸驱动这个是上电的,可以识别用户的触摸事件,驱动层面识别双击后触发点亮屏幕。

下面针对2个方案进行尝试性调研

方案1可以直接framework层面修改

因为所有的power按键逻辑处理,都是需要经过PhoneWindowManager这里类进行的。所以考虑是否可以在PhoneWindowManager中对原有的power进行待机和唤醒操作进行修改。
核心思路步骤如下:

1.需要对power按键的原有息屏亮屏处理逻辑都进行屏蔽,即先让power按键按了之后没有任何反应

2.再针对power按键进行新的逻辑处理,只需要添加背光设置操作,息屏背光设置为0,亮屏恢复正常背光值

   public static  boolean isScreenLightOff = false;
    void setLightOff(){
        LightsManager lights = LocalServices.getService(LightsManager.class);
        LogicalLight mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
        isScreenLightOff =true;
        mBacklight.setBrightness(0);
    }

    void setLightOn(){
        LightsManager lights = LocalServices.getService(LightsManager.class);
        LogicalLight mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
        int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS,
                mPowerManager.getDefaultScreenBrightnessSetting(),UserHandle.USER_CURRENT_OR_SELF);
        isScreenLightOff =false;
        mBacklight.setBrightness(brightness);
    }

3、需要对触摸事件进行的相关的识别,让触摸事件在背光为0状态不进行派发到任何的app,只是在InputDispatcherh中进识别双击,如果一旦双击则重新调用setLightOn,让屏幕点亮

该方案总结:
1、这个修改波及很大,修改了很多的原生逻辑,很多时候也有其他逻辑修改相关的背光情况,经常可能出现修改不全等情况
2、因为本质只是关闭了背光而已,所以整体app都还在正常运行,没有进入待机状态,所以整体功耗肯定比以前大很多

方案1缺点都比较致命,所以基本上完全不推荐该方案

方案2 驱动层面实现

这个方案属于大部分厂商都使用的现成方案,具体代码和实现细节暂时不进行深入,这里可拿相关手机来进调研看看是如何做到的。

1、有一个设置开关来启动双击亮屏功能
在这里插入图片描述
打开后既可以实现在灭屏时候点击触摸屏幕2下既可以点亮

2、在灭屏时候连续点击屏幕两下,通过getevent看看是不是传递的触摸事件?

test@test:~/disk2/nx563j_aosp14$ adb shell getevent -lrt
add device 1: /dev/input/event8
  name:     "msm8998-tasha-snd-card Button Jack"
add device 2: /dev/input/event7
  name:     "msm8998-tasha-snd-card Headset Jack"
add device 3: /dev/input/event6
  name:     "uinput-fpc"
add device 4: /dev/input/event1
  name:     "proximity"
add device 5: /dev/input/event2
  name:     "light"
add device 6: /dev/input/event0
  name:     "qpnp_pon"
add device 7: /dev/input/event3
  name:     "hall_device"
add device 8: /dev/input/event4
  name:     "nubia_synaptics_dsx"
add device 9: /dev/input/event5
  name:     "gpio-keys"
[  485422.726460] /dev/input/event4: EV_KEY       KEY_WAKEUP           DOWN                
[  485422.726460] /dev/input/event4: EV_SYN       SYN_REPORT           00000000            
[  485422.726758] /dev/input/event4: EV_KEY       KEY_WAKEUP           UP                  
[  485422.726758] /dev/input/event4: EV_SYN       SYN_REPORT           00000000             rate 3355
[  485422.791717] /dev/input/event1: EV_REL       REL_RZ               0000000a            
[  485422.791717] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             rate 15
[  485422.878681] /dev/input/event1: EV_REL       REL_RZ               0000000a            
[  485422.878681] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             rate 11

明显可以看出getevent获取的数据这里根本没出现有任何的触摸事件的abs数据,而是变成的KEY_WAKEUP的Key事件类型,从而达到唤醒屏幕的目的,这个KEY_WAKEUP就是和正常按下POWER按钮事件一样。
正常Power的getevent展示如下:


[  485662.684341] /dev/input/event0: EV_KEY       KEY_POWER            DOWN                
[  485662.684341] /dev/input/event0: EV_SYN       SYN_REPORT           00000000            
[  485662.801875] /dev/input/event1: EV_REL       REL_RZ               0000000a            
[  485662.801875] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             rate 8
[  485662.827897] /dev/input/event0: EV_KEY       KEY_POWER            UP                  
[  485662.827897] /dev/input/event0: EV_SYN       SYN_REPORT           00000000             rate 38

KEY_WAKEUP和KEY_POWER的主要区别在于它们的功能和用途不同。‌

KEY_WAKEUP通常用于在设备休眠状态下通过特定按键唤醒设备,而KEY_POWER则用于控制设备的开关机功能。

KEY_WAKEUP是一个特定的按键值,用于在设备休眠时通过中断唤醒设备。当设备处于休眠状态时,通过按下具有唤醒功能的按键(如PowerKey),会触发中断,从而唤醒设备。这与设备的电源管理密切相关,允许用户在不完全关闭设备的情况下快速恢复使用‌12。

KEY_POWER则是指用于开关机的按键,通常在设备完全关闭时使用。按下KEY_POWER键会触发设备的关机或重启过程,这与设备的启动和关闭操作直接相关‌24。

在技术实现上,KEY_WAKEUP通常与设备的输入系统(如GPIO)相关联,并在设备休眠时设置为中断源。当按键被按下时,会触发中断,从而使设备从休眠状态唤醒。而KEY_POWER键的实现则涉及到更底层的硬件控制,确保设备能够执行开关机操作‌12。
即无论WAKEUP还是POWER都可以唤醒休眠点亮屏幕。
方案总结:
驱动层面实现方案为啥成为各个厂商主流方案,主要有以下几点:

1、完全不需要修改任何的framework层面代码,不需要修改破坏任何的原生power逻辑

2、驱动部分直接就识别了双击,然后上报的一个KEY_WAKEUP事件,非常简单的实现了唤醒设备

更多framework技术干货,请关注下面“千里马学框架”

实现 Android 双击亮屏的方式可以通过重写 Activity 的 onTouchEvent 方法,监听用户的手势操作。具体实现步骤如下: 1. 定义一个变量记录用户点击屏幕的时间,初始值为0。 2. 重写 Activity 的 onTouchEvent 方法,监听用户手势操作。 3. 在 onTouchEvent 方法中,根据用户手势操作的类型,判断是否为双击事件。 4. 如果是双击事件,则获取系统的 PowerManager 对象,并调用其 wakeUp 方法,唤醒屏幕。 以下是一个简单的示例代码: ```java public class MainActivity extends AppCompatActivity { private long lastClickTime = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { long currentTime = System.currentTimeMillis(); if (currentTime - lastClickTime < 500) { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = pm.newWakeLock( PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "DoubleTapWakeLock"); wakeLock.acquire(1000); } lastClickTime = currentTime; } return super.onTouchEvent(event); } } ``` 在这个示例代码中,我们在 onTouchEvent 方法中判断两次点击时间间隔是否小于 500 毫秒,如果是,则认为是双击事件,调用 PowerManager 的 wakeUp 方法唤醒屏幕。注意,这里需要申请 WakeLock 权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值