Android13锁屏或灭屏状态下,快速按两次音量下键实现打开闪光灯功能

实现思路:

1、发送广播

    WindowManagerService循环读取下面按键消息并分发给窗口,在消息分发前会在PhoneWindowManager.interceptKeyBeforeQueueing方法中进行消息的过滤。因此该实现方式为在消息分发前的interceptKeyBeforeQueueing方法中监听当前按键为音量下键,如果当前状态为锁屏状态,并按键为音量下键,且两次按键间隔时间小于800ms时发送广播--“com.custom.volume_down”

具体实现方式如下:

sys\frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java

private long lastTime = 0;

@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
    final int keyCode = event.getKeyCode();
    final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;

    ......
    switch (keyCode) {
        ......
        case KeyEvent.KEYCODE_VOLUME_DOWN:
            // add start
            String volume_down = SystemProperties.get("persist.sys.double.volume_down");
            if (DEBUG_INPUT) {
                Log.i(TAG, "interceptKeyBeforeQueueing:"
                                          + " VOLUME KEYCODE_VOLUME_DOWN"
                                          + " volume_down = " + volume_down
                                          + " keyguardActive = " + keyguardActive
                                          + " lastTime = " + lastTime
                              );
            }
            if (down) { //按键按下
                if (volume_down != null && !volume_down.equals("0")) {
                    if (keyguardActive) {//锁屏
                        if (System.currentTimeMillis() - lastTime <= 800) {
                            mContext.sendBroadcast(new Intent("com.custom.volume_down"));
                        lastTime = 0;
                        } else {
                                lastTime = System.currentTimeMillis();
                        }
                        return 0;
                    }
                }
            }
        // add end
    case KeyEvent.KEYCODE_VOLUME_UP:
    ......

2、接收广播

接收到广播“com.custom.volume_down”后打开或关闭闪光灯

private CameraManager mCameraManager;
private boolean mFlashlightEnabled = false;

private String mCameraId;
private Handler mHandler;
private void initBroadcastReceiver(Context context) {
    mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
    tryInitCamera();
    IntentFilter filter = new IntentFilter();
    filter.addAction("com.custom.volume_down");
    context.registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            LogUtils.i(TAG, "action = " + action);
            if (action != null) {
                if (action.equals("com.custom.volume_down")) {
                    String volume_down =     SysProUtils.get("persist.sys.double.volume_down");
                    LogUtils.i(TAG, "volume_down = " + volume_down);
                    if (volume_down != null) {
                        if (volume_down.equals("1")) {
                            setFlashlight(!mFlashlightEnabled);
                        }
                    }
                }
            }
        }
    }, filter);
}

private synchronized void ensureHandler() {
    if (mHandler == null) {
        HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();
        mHandler = new Handler(thread.getLooper());
    }
}

public void setFlashlight(boolean enabled) {
    synchronized (this) {
        if (mCameraId == null) return;
        if (mFlashlightEnabled != enabled) {
            mFlashlightEnabled = enabled;
            try {
                mCameraManager.setTorchMode(mCameraId, enabled);
            } catch (CameraAccessException e) {
                Log.e(TAG, "Couldn't set torch mode", e);
                mFlashlightEnabled = false;
            }
        }
    }
}

private String getCameraId() throws CameraAccessException {
    String[] ids = mCameraManager.getCameraIdList();
    for (String id : ids) {
        CameraCharacteristics c = mCameraManager.getCameraCharacteristics(id);
        Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
        Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING);
        if (flashAvailable != null && flashAvailable
                && lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_BACK) {
            return id;
        }
    }
    return null;
}

private void tryInitCamera() {
    try {
        mCameraId = getCameraId();
    } catch (Throwable e) {
        Log.e(TAG, "Couldn't initialize.", e);
        return;
    }

    if (mCameraId != null) {
        ensureHandler();
        mCameraManager.registerTorchCallback(mTorchCallback, mHandler);
    }
}

private final CameraManager.TorchCallback mTorchCallback =
        new CameraManager.TorchCallback() {

            @Override
            @WorkerThread
            public void onTorchModeChanged(String cameraId, boolean enabled) {
                if (TextUtils.equals(cameraId, mCameraId)) {
                    setTorchMode(enabled);
                }
            }
        };

private void setTorchMode(boolean enabled) {
    synchronized (CommModule.this) {
        mFlashlightEnabled = enabled;
    }
}

3、在settings源码中添加控制

在settings中添加开关按钮。

如果打开开关,双击音量下键,打开或关闭闪光灯。

如果关闭开关,双击音量下键,不做任何处理。

在res/xml/accessibility_settings.xml中添加

+        <SwitchPreference
+            android:key="accessibility_flashlight"
+            android:persistent="false"
+            android:icon="@drawable/ic_flashlight"
+            android:summary="@string/accessibility_settings_flashlight_summary"
+            android:title="@string/accessibility_settings_flashlight_preference_title"
+            settings:searchable="true"
+            settings:controller="com.android.settings.accessibility.FlashlightPreferenceController"/>

在app\src\main\java\com\android\settings\accessibility目录下新建FlashlightPreferenceController.java

package com.android.settings.accessibility;

import android.content.Context;
import android.os.SystemProperties;
import android.text.TextUtils;

import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;

/**
 * A toggle preference controller for audio description
 */
public class FlashlightPreferenceController extends TogglePreferenceController {

    static final String PREF_KEY = "accessibility_flashlight";

    public FlashlightPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
    }

    @Override
    public boolean isChecked() {
        String volume_down = SystemProperties.get("persist.sys.double.volume_down");
        if (!TextUtils.isEmpty(volume_down)) {
            if (volume_down.equals("1")) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        SystemProperties.set("persist.sys.double.volume_down", isChecked ? "1" : "0");
        return true;
    }

    @Override
    public int getAvailabilityStatus() {
        String volume_down = SystemProperties.get("persist.sys.double.volume_down");
        return TextUtils.isEmpty(volume_down) ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
    }

    @Override
    public int getSliceHighlightMenuRes() {
        return R.string.menu_key_accessibility;
    }
}

InputDispatcher拦截逻辑_interceptkeybeforequeueing-CSDN博客

Android事件拦截_interceptkeybeforequeueing-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/583232.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

看看大家都在做哪些有趣的项目

最近发现两个比较有趣的项目 1.中国独立开发者项目列表 该项目旨在聚合中国独立开发者的项目&#xff0c;分享开发者们正在进行的工作&#xff0c;项目列表包括网站或 App&#xff0c;并且正在持续更新中 项目分为程序员版和主版面&#xff1a; 程序员版&#xff1a;用户是程…

docker compose安装redis

一、安装准备 在docker hub查看redis镜像版本。查看地址如下&#xff1a; Dockerhttps://hub-stage.docker.com/_/redis/tags 二、拉取docker镜像 我这里用redis:6.2.14版本&#xff0c;先拉取镜像。命令如下&#xff1a; docker pull redis:6.2.14 查看刚刚下载的镜像&am…

M2 Mac mini跑Llama3

前言 在4-19左右&#xff0c;Meta 宣布正式推出下一代开源大语言模型 Llama 3&#xff1b;共包括 80 亿和 700 亿参数两种版本&#xff0c;号称 “是 Llama 2 的重大飞跃”&#xff0c;并为这些规模的 LLM 确立了新的标准。实际上笔者早就体验过&#xff0c;只不过自己电脑没什…

nuxt3使用记录五:禁用莫名其妙的Tailwind CSS(html文件大大减小)

发现这个问题是因为&#xff0c;今天我突然很好奇&#xff0c;我发现之前构建的自动产生的200.html和404.html足足290k&#xff0c;怎么这么大呢&#xff1f;不是很占用我带宽&#xff1f; 一个啥东西都没有的静态页面&#xff0c;凭啥这么大&#xff01;所以我就想着手动把他…

matlab新手快速上手6(引力搜索算法)

本文根据一个较为简单的matlab引力搜索算法框架详细分析蚁群算法的实现过程&#xff0c;对matlab新手友好&#xff0c;源码在文末给出。 引力搜索算法简介&#xff1a; 引力搜索算法是一种启发式优化算法&#xff0c;最初于2009年由伊朗的Esmat Rashedi、Hossein Nezamabadi-p…

MyBatis(注解方式操作)

文章目录 1.注解方式操作文件目录1.快速入门&#xff08;完整步骤&#xff09;1.pom.xml&#xff08;完整&#xff09;2.resources/jdbc.properties外部配置文件&#xff08;根据实际情况修改参数&#xff09;3.在resources/mybatis-config.xml&#xff08;完整&#xff09;中配…

Linux基本指令(3)

目录 时间相关的指令&#xff1a; 1.在显示方面&#xff0c;使用者可以设定欲显示的格式&#xff0c;格式设定为一个加好后接数个标记&#xff0c;其中常用的标记列表如下&#xff1a; 2.在设定时间方面&#xff1a; 3.时间戳&#xff1a; Cal指令&#xff1a; find指令&a…

韩国云主机安装AMP环境要求科普

AMP环境&#xff0c;即Apache、MySQL和PHP的组合&#xff0c;是许多网站开发者和运维人员常用的环境配置。在韩国云主机上安装AMP环境&#xff0c;需要满足一定的要求以确保顺利运行和高效性能。下面我们将对韩国云主机安装AMP环境的要求进行科普。 首先&#xff0c;韩国云主机…

深入探索MySQL锁机制:揭秘死锁原因与RC隔离级别下的事务处理

MySQL锁的类型及死锁概述 在数据库系统中&#xff0c;为了保证事务可以正确地访问数据&#xff0c;防止数据不一致&#xff0c;通常会使用锁机制。MySQL作为广泛使用的数据库之一&#xff0c;其InnoDB存储引擎提供了多种锁类型&#xff0c;主要包括行锁&#xff08;Record Loc…

每日一题(力扣55):跳跃游戏--贪心

刚开始像这道题&#xff0c;想的是这么从当前可以走的那几步中选择一步&#xff0c;所以一坨屎一样的代码 class Solution { public:bool canJump(vector<int>& nums) {int nnums.size();int step0;int u0;int u_max0;int step_size0;int max_size0;int loci0;while…

机器学习-11-卷积神经网络-基于paddle实现神经网络

文章目录 总结参考本门课程的目标机器学习定义第一步&#xff1a;数据准备第二步&#xff1a;定义网络第三步&#xff1a;训练网络第四步&#xff1a;测试训练好的网络 总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍基于paddle实现神经网络。 参考 MNIST 训练_副…

FreeRTOS:3.信号量

FreeRTOS信号量 参考链接&#xff1a;FreeRTOS-信号量详解_freertos信号量-CSDN博客 目录 FreeRTOS信号量一、信号量是什么二、 FreeRTOS信号量1、二值信号量1、获取信号量2、释放信号量 2、计数信号量3、互斥信号量1、优先级反转2、优先级继承3、源码解析1、互斥量创建2、获取…

FFmpeg常用结构体、关键函数、ffplay.c分析

一、常用结构体&#xff1a; 1、AVFormatContext结构体&#xff1a; AVFormatContext是一个贯穿全局的数据结构&#xff0c;很多函数都要用它作为参数。FFmpeg代码中对这个数据结构的注释是format I/O context&#xff0c;此结构包含了一个视频流的格式内容。其中存有AVIputFor…

电脑使用笔记

1.电脑亮度调节 亮度&#xff1a;50 对比度&#xff1a;45 暗部平衡&#xff1a;40

毕业设计注意事项(嘉庚学院2024届更新中)

1.开题 根据学院发的开题报告模板完成&#xff0c;其中大纲部分可参考资料。 2.毕设以及实习 2.1 毕设 根据资料中的毕设评价标准&#xff0c;对照工作量 2.2 实习材料提交 2.2.1 校外实习 实习前&#xff1a;根据学院要求&#xff0c;填写好实习承诺书&#xff0c;实习单位…

【数据结构初阶】时间复杂度和空间复杂度详解

今天我们来详细讲讲时间复杂度和空间复杂度&#xff0c;途中如果有不懂的地方可翻阅我之前文章。 个人主页&#xff1a;小八哥向前冲~-CSDN博客 数据结构专栏&#xff1a;数据结构【c语言版】_小八哥向前冲~的博客-CSDN博客 c语言专栏&#xff1a;c语言_小八哥向前冲~的博客-CS…

网络服务SSH-远程访问及控制

一.SSH远程管理 1.SSH介绍 SSH&#xff08;Secure Shell&#xff09;是一种安全通道协议&#xff0c;最早是由芬兰的一家公司开发出来&#xff0c;并且在IETF &#xff08;Internet Engineering Task Force&#xff09;的网络草案基础上制定而成的标准协议。主要用来实现字符…

合规基线:让安全大检查更顺利

前言 说起安全检查&#xff0c;安全从业人员可能都非常熟悉“安全标准”概念。所有企事业单位网络安全建设都需要满足来自于国家或监管单位的安全标准&#xff0c;如等保2.0、CIS安全标准等。安全标准&#xff0c;还有一个叫法就是“安全基线”。字典上对“基线”的解释是&…

【PostgreSQL】pg触发器介绍

注: 本文为云贝教育 刘峰 原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 触发器是在对指定表执行指定更改操作&#xff08;SQL INSERT、UPDATE、DELETE 或 TRUNCATE 语句&#xff09;时自动运行的一组操作…

Java全栈开发前端+后端(全栈工程师进阶之路)-环境搭建

在课程开始前我们要配置好我们的开发环境&#xff0c;这里我的电脑太乱了&#xff0c;我使用vm虚拟机进行搭建开发环境&#xff0c;如果有需要环境的或者安装包&#xff0c;可以私信我。 那我们开始 首先我们安装数据库 这里我们使用小皮面板 小皮面板(phpstudy) - 让天下没…
最新文章