Android中apk中息屏/锁屏、亮屏/解锁 新思路

时间:2021-01-26 18:39:03

备注:

1.【项目的apk是跑在自己Android6.0主板设备上,上层是拥有Root权限的】;
2.【本次博客提到息屏/锁屏是指在BroadcastReceiver中接收到ACTION_SCREEN_ON的操作;亮屏/解锁是接收到Intent.ACTION_SCREEN_OFF操作】;

业务需求

  • 公司的一个设备是一个带显示屏Android(6.0 Root)板的智能终端,有人体感应头,现在需要在apk上层做逻辑是感应到人就点亮屏(这个easy),默认2分钟后如果没感应到人就息屏
  • 先说说我的最终息屏解决方式是Runtime调用Linux-shell发送命令"input keyevent 26"模拟电源按键息屏;【项目的apk是跑在自己Android6.0主板设备上,上层是拥有Root权限的】

开工

  • 先想到是直接用PowerManager.WakeLock的acquire()和release()配合一下就搞定了(当初就是这天真),结果是点屏幕是没问题的,但是就是不能息屏;
  • 本人是菜鸡直接就是百度了,结果网上就是一波PowerManager应用反射goToSleep(long time);如获至宝,然而goToSleep需要Requires signature permission系统签名,还是很折腾的,自己搞不定继续百度希望有大佬贴出实现代码;

  • 在网上逛一圈发现关于PowerManager息屏基本上都是将理论,没有发现贴出来代码的,有些贴出来的可能是低版本系统上编译的吧,在我的AS上也是不能编译通过;

  • 后来看到用DevicePolicyManager实现的就是代码量有点大,而且还要申请系统管理权限,有点烦但是在网上copy出一个demo,在设备上run一下功能是Ok的于是学习一下API就开始往工程里塞了

  • **

峰回路转

就在码农不辞辛苦的CV的时候,我技术老大(Android固件就是他搞的),跟我说你样去调用API去执行也是最终调用系统Service去灭屏,就是和ADB命令input keyevent 26模拟电源键息屏是一样的;听他一说瞬间发现自己好傻逼啊(系统是root过的可以直接调用Runtime调用Linux-shell发送ADB命令就可以啦);

#常见的模拟按键ADB命令
  • input keyevent 26 电源键
  • input keyevent 24 音量+键
  • input keyevent 25 音量-键
  • input keyevent 3 Home键
  • input keyevent 4 返回键
  • input keyevent 5 呼叫键
  • input keyevent 6 挂断键
  • input keyevent 19 导航
  • input keyevent 20 导航
  • input keyevent 21 导航
  • input keyevent 22 导航
  • ……
    部分命令记不清参考:adb shell 模拟按键,触摸事件

最后的结果就是只需要一个Utils类利用Runtime调用Linux-shell发送命令"input keyevent 26"模拟电源按键息屏就搞定了息屏的需求:
Utils类:Android Root根权限的检查获取类(项目里有串口通信,所以就修改几行代码的事情了,成功的躲过了DevicePolicyManager中臃肿的代码量和授权)

于是简单修改了一下代码工具类贴出我的代码:
【需要注意的是在我的项目里apk是跑在自己的设备上,固件是自己定制(只是修改一些标签),系统也root过的下面代码在我的环境是正常的,那位小伙伴参考需要根据自己apk运行环境】


亮屏逻辑代码:

//亮屏逻辑代码
private PowerManager powerManager;
private PowerManager.WakeLock wakeLock;
public void openScreenOn() {
if (powerManager == null) {
            powerManager = (PowerManager) AppApplication.getApplicationContexts().getSystemService(Context.POWER_SERVICE);
        }
if (wakeLock == null) {
            wakeLock = powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");
        }
boolean ifOpen = powerManager.isScreenOn();
if (!ifOpen) {
            //屏幕会持续点亮
            wakeLock.acquire();
            //释放锁,屏幕熄灭。
            wakeLock.release();
        }
}

在需要调用息屏的逻辑调用代码:


//在需要调用息屏的逻辑调用代码
 boolean root = AndroidRootUtils.checkDeviceRoot();
        if(root){
            AndroidRootUtils.execRootCmd("input keyevent 26");
        }

Android Root根权限工具类:


//AndroidRootUtils Root根权限工具类
public class AndroidRootUtils {
    /** * * 判断机器Android是否已经root,即是否获取root权限 */
    public static boolean checkDeviceRoot() {
        boolean resualt = false;
            int ret = execRootCmdSilent("echo test"); // 通过执行测试命令来检测
            if (ret != -1) {
                Log.i("checkDeviceRoot", "this Device have root!");
                resualt = true;
            } else {
                resualt = false;
                Log.i("checkDeviceRoot", "this Device not root!");
            }
        return resualt;
    }

    /** * 执行命令并且输出结果 */
    public static String execRootCmd(String cmd) {
        String result = "";
        DataOutputStream dos = null;
        DataInputStream dis = null;
        try {
            Process p = Runtime.getRuntime().exec("su");// 经过Root处理的android系统即有su命令
            dos = new DataOutputStream(p.getOutputStream());
            dis = new DataInputStream(p.getInputStream());
            dos.writeBytes(cmd + "\n");
            dos.flush();
            dos.writeBytes("exit\n");
            dos.flush();
            String line = null;
            while ((line = dis.readLine()) != null) {
                result += line;
            }
            p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dis != null) {
                try {
                    dis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    /** * 执行命令但不关注结果输出 */
    public static int execRootCmdSilent(String cmd) {
        int result = -1;
        DataOutputStream dos = null;
        try {
            Process p = Runtime.getRuntime().exec("su");
            dos = new DataOutputStream(p.getOutputStream());
            dos.writeBytes(cmd + "\n");
            dos.flush();
            dos.writeBytes("exit\n");
            dos.flush();
            p.waitFor();
            result = p.exitValue();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}