无障碍服务屏蔽_关闭无障碍服务快捷方式

news2024/11/13 15:44:45

问题描述:
1)部分app 存在无障碍服务功能,需要关闭
2)对于客户自研App,自己具备系统签名自己直接开启了无障碍服务并且打开了无障碍服务快捷方式,如何关闭无障碍服务快捷开关

文章目录

  • 问题现象
    • 问题描述
  • 屏蔽app无障碍服务显示
  • 屏蔽快捷模式方案
      • 举例说明:针对酷狗音乐
      • 举例说明:针对智能家居 App测试


问题现象

现象如下图所示
在这里插入图片描述
在这里插入图片描述

问题描述

  • 在无障碍功能列表里面一般都是第三方app,我们不允许客户能够具备这个权限,所以需要屏蔽掉
  • 针对自研具备系统签名app,不允许客户自己开启无障碍服务快捷方式、或者 我们每次自己去控制无障碍服务快捷开关

屏蔽app无障碍服务显示

思路如下

  1. 搜索无障碍服务相关文字搜索,如下:
 <string name="accessibility_text_and_display_title" msgid="1398507755501334961">"文字和显示"</string>
    <string name="accessibility_turn_screen_darker_title" msgid="5986223133285858349">"调暗屏幕"</string>
    <string name="interaction_control_category_title" msgid="2696474616743882372">"互动控制"</string>
    <string name="accessibility_tap_assistance_title" msgid="1058913033421048284">"时间控件"</string>
    <string name="accessibility_system_controls_title" msgid="6403287349518987624">"系统控件"</string>
    <string name="user_installed_services_category_title" msgid="2639470729311439731">"已下载的应用"</string>
    <string name="experimental_category_title" msgid="898904396646344152">"实验性功能"</string>
	
  1. 通过1 找到无障碍模式布局文件 accessibility_settings.xml
    从布局对比可以看到,这个已下载的应用,本身子数据也是动态添加的,其它的快捷菜单子数据是配置的。
      <PreferenceCategory
        android:key="user_installed_services_category"
        android:persistent="false"
        android:title="@string/user_installed_services_category_title"/>
  1. 通过2 找到 AccessibilitySettings.java
    已下载的内容:CATEGORY_DOWNLOADED_SERVICES
 private static final String CATEGORY_DOWNLOADED_SERVICES = "user_installed_services_category";

-final PreferenceCategory downloadedServicesCategory =
                mCategoryToPrefCategoryMap.get(CATEGORY_DOWNLOADED_SERVICES);
-》集合mCategoryToPrefCategoryMap 赋值:
 private void initializeAllPreferences() {
        for (int i = 0; i < CATEGORIES.length; i++) {
            PreferenceCategory prefCategory = findPreference(CATEGORIES[i]);
            mCategoryToPrefCategoryMap.put(CATEGORIES[i], prefCategory);
        }
    }
	

根据2 中的推测,找到mCategoryToPrefCategoryMap 中,已下载的 赋值地方。

  ->  final PreferenceCategory downloadedServicesCategory =
                mCategoryToPrefCategoryMap.get(CATEGORY_DOWNLOADED_SERVICES);
				
	  downloadedServicesCategory 找到它赋值子类的地方:
	  
	->
    for (int i = 0, count = preferenceList.size(); i < count; ++i) {
            final RestrictedPreference preference = preferenceList.get(i);
            final ComponentName componentName = preference.getExtras().getParcelable(
                    EXTRA_COMPONENT_NAME);
            PreferenceCategory prefCategory = downloadedServicesCategory;
            // Set the appropriate category if the service comes pre-installed.
            if (mPreBundledServiceComponentToCategoryMap.containsKey(componentName)) {
                prefCategory = mPreBundledServiceComponentToCategoryMap.get(componentName);
            }
            prefCategory.addPreference(preference);
            mServicePreferenceToPreferenceCategoryMap.put(preference, prefCategory);
        }	

这个地方,通过 componentName 的信息,如果含有了 需要屏蔽的包名 则 continue 即可,不让添加到prefCategory中 即可
修改后的代码如下:

 for (int i = 0, count = preferenceList.size(); i < count; ++i) {
            final RestrictedPreference preference = preferenceList.get(i);
            final ComponentName componentName = preference.getExtras().getParcelable(
                    EXTRA_COMPONENT_NAME);
					
			  String pkgName=  componentName.getPackageName();
            Log.d(TAG,"pkgName:"+pkgName);

          if("com.sohu.inputmethod.sogou".equals(pkgName)){  //这个地方通过包名来判断,进行屏蔽
            
			Log.d(TAG,"ping bi:"+pkgName);

		   continue;
          }		
					
            PreferenceCategory prefCategory = downloadedServicesCategory;
            // Set the appropriate category if the service comes pre-installed.
            if (mPreBundledServiceComponentToCategoryMap.containsKey(componentName)) {
                prefCategory = mPreBundledServiceComponentToCategoryMap.get(componentName);
            }
            prefCategory.addPreference(preference);
            mServicePreferenceToPreferenceCategoryMap.put(preference, prefCategory);
        }

屏蔽快捷模式方案

  1. 搜索代码 “快捷方式,找到对应位置”
  <string name="accessibility_shortcut_title" msgid="8125867833704517463">"<xliff:g id="SERVICE">%1$s</xliff:g>快捷方式"</string>
  1. 通过R.string.accessibility_shortcut_title 找到 AccessibilityShortcutPreferenceFragment
    找到一些相关的代码

相关代码加载布局

/**
 * Base class for accessibility fragments shortcut functions and dialog management.
 */
 
     @VisibleForTesting
    void setupEditShortcutDialog(Dialog dialog) {
        final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut);
        mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox);
        setDialogTextAreaClickListener(dialogSoftwareView, mSoftwareTypeCheckBox);

        final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut);
        mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox);
        setDialogTextAreaClickListener(dialogHardwareView, mHardwareTypeCheckBox);

        updateEditShortcutDialogCheckBox();
    }




@Override
    public Dialog onCreateDialog(int dialogId) {
        final Dialog dialog;
        switch (dialogId) {
            case DialogEnums.EDIT_SHORTCUT:
                final CharSequence dialogTitle = getPrefContext().getString(
                        R.string.accessibility_shortcut_title, getLabelName());
                final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent())
                        ? AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC_SUW :
                        AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC;
                dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                        getPrefContext(), dialogType, dialogTitle,
                        this::callOnAlertDialogCheckboxClicked);
                setupEditShortcutDialog(dialog);
                return dialog;
            case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
                dialog = AccessibilityGestureNavigationTutorial
                        .createAccessibilityTutorialDialog(getPrefContext(),
                                getUserShortcutTypes());
                dialog.setCanceledOnTouchOutside(false);
                return dialog;
            default:
                throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
        }

->AccessibilityGestureNavigationTutorial.java

checkBox 点击事件地方

    @Override
    public void onToggleClicked(ShortcutPreference preference) {
        if (getComponentName() == null) {
            return;
        }

        final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(getPrefContext(),
                getComponentName().flattenToString(), AccessibilityUtil.UserShortcutType.SOFTWARE);
        if (preference.isChecked()) {
            AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes,
                    getComponentName());
            showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
        } else {
            AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes,
                    getComponentName());
        }
        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
    }

这里AccessibilityUtil 有两个方法 optInAllValuesToSettings optOutAllValuesFromSettings 而且有 getComponentName 说明是对某个应用进行设置,进去看下具体代码

 /**
     * Opts in component name into multiple {@code shortcutTypes} colon-separated string in
     * Settings.
     *
     * @param context The current context.
     * @param shortcutTypes  A combination of {@link UserShortcutType}.
     * @param componentName The component name that need to be opted in Settings.
     */
    static void optInAllValuesToSettings(Context context, int shortcutTypes,
            @NonNull ComponentName componentName) {
        if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) {
            optInValueToSettings(context, UserShortcutType.SOFTWARE, componentName);
        }
        if (((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE)) {
            optInValueToSettings(context, UserShortcutType.HARDWARE, componentName);
        }
    }
	

/**
     * Opts out component name into multiple {@code shortcutTypes} colon-separated string in
     * Settings.
     *
     * @param context The current context.
     * @param shortcutTypes A combination of {@link UserShortcutType}.
     * @param componentName The component name that need to be opted out from Settings.
     */
    static void optOutAllValuesFromSettings(Context context, int shortcutTypes,
            @NonNull ComponentName componentName) {
        if ((shortcutTypes & UserShortcutType.SOFTWARE) == UserShortcutType.SOFTWARE) {
            optOutValueFromSettings(context, UserShortcutType.SOFTWARE, componentName);
        }
        if (((shortcutTypes & UserShortcutType.HARDWARE) == UserShortcutType.HARDWARE)) {
            optOutValueFromSettings(context, UserShortcutType.HARDWARE, componentName);
        }
    }
 

实际根据AccessibilityUtil.java 日志分析,

举例说明:针对酷狗音乐

打开无障碍快捷方式:

AccessibilityUtil       com.android.settings                 D  optInAllValuesToSettings  shortcutTypes:1   pkgName:com.kugou.android   className:com.kugou.ringtone.permission.accessibilitysuper.service.AccessibilitySuperService
AccessibilityUtil       com.android.settings                 D  optInAllValuesToSettings  ->optInValueToSettings  SOFTWARE
AccessibilityUtil       com.android.settings                 D  optInValueToSettings  targetKey:accessibility_button_targets   targetString:
AccessibilityUtil       com.android.settings                 D  optInValueToSettings  componentName flattenToStr:com.kugou.android/com.kugou.ringtone.permission.accessibilitysuper.service.AccessibilitySuperService
AccessibilityUtil       com.android.settings                 D  optInValueToSettings  targetKey:accessibility_button_targets   joiner:com.kugou.android/com.kugou.ringtone.permission.accessibilitysuper.service.AccessibilitySuperService

最终 optInValueToSettings 方法,调用:

Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString());
Log.d(TAG,"optInValueToSettings  targetKey:"+targetKey+"   joiner:"+ joiner.toString());

关闭无障碍快捷方式:

AccessibilityUtil       com.android.settings                 D  optOutAllValuesFromSettings  shortcutTypes:1   pkgName:com.kugou.android   className:com.kugou.ringtone.permission.accessibilitysuper.service.AccessibilitySuperService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  shortcutType:1   pkgName:com.kugou.android   className:com.kugou.ringtone.permission.accessibilitysuper.service.AccessibilitySuperService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  targetKey:accessibility_button_targets   targetString:com.kugou.android/com.kugou.ringtone.permission.accessibilitysuper.service.AccessibilitySuperService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  targetKey:accessibility_button_targets   joiner.toString():

最终 optOutValueFromSettings 方法里面调用:

Settings.Secure.putString(context.getContentResolver(), targetKey, joiner.toString());
Log.d(TAG,"optOutValueFromSettings  targetKey:"+targetKey+"   joiner.toString():"+joiner.toString());

所以,针对 不同app,取消权限 需要调用 对应的targetkey 的value 置空即可

举例说明:针对智能家居 App测试

打开快捷方式 日志如下:

AccessibilityUtil       com.android.settings                 D  optInAllValuesToSettings  shortcutTypes:3   pkgName:com.deling.launcher   className:com.hrs.tools.services.ToolsAccessibilityService
AccessibilityUtil       com.android.settings                 D  optInAllValuesToSettings  ->optInValueToSettings  SOFTWARE
AccessibilityUtil       com.android.settings                 D  optInValueToSettings  targetKey:accessibility_button_targets   targetString:
AccessibilityUtil       com.android.settings                 D  optInValueToSettings  componentName flattenToStr:com.deling.launcher/com.hrs.tools.services.ToolsAccessibilityService
AccessibilityUtil       com.android.settings                 D  optInValueToSettings  targetKey:accessibility_button_targets   joiner:com.deling.launcher/com.hrs.tools.services.ToolsAccessibilityService

打开快捷方式开关:涉及到相关的componentName 如下:

pkgName:com.deling.launcher   className:com.hrs.tools.services.ToolsAccessibilityService
componentName flattenToStr:com.deling.launcher/com.hrs.tools.services.ToolsAccessibilityService
两个app targetKey:accessibility_button_targets  一样的

关闭快捷方式,日志如下:

AccessibilityUtil       com.android.settings                 D  optOutAllValuesFromSettings  shortcutTypes:3   pkgName:com.deling.launcher   className:com.hrs.tools.services.ToolsAccessibilityService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  shortcutType:1   pkgName:com.deling.launcher   className:com.hrs.tools.services.ToolsAccessibilityService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  targetKey:accessibility_button_targets   targetString:com.deling.launcher/com.hrs.tools.services.ToolsAccessibilityService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  targetKey:accessibility_button_targets   joiner.toString():
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  shortcutType:2   pkgName:com.deling.launcher   className:com.hrs.tools.services.ToolsAccessibilityService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  targetKey:accessibility_shortcut_target_service   targetString:com.deling.launcher/com.hrs.tools.services.ToolsAccessibilityService
AccessibilityUtil       com.android.settings                 D  optOutValueFromSettings  targetKey:accessibility_shortcut_target_service   joiner.toString():


所以解决方案,每次开机后,或者在哪个位置,关闭对应的快捷方式即可,方法:

Settings.Secure.putString(context.getContentResolver(), targetKey, "");

针对 X7 快捷,实现方式: 取消快捷

Settings.Secure.putString(context.getContentResolver(), "accessibility_button_targets", "");
Settings.Secure.putString(context.getContentResolver(), "accessibility_shortcut_target_service", "");

实际demo 功能验证:

   //ToastUtils.showShort("测试快捷模式关闭");
   Settings.Secure.putString(getContentResolver(), "accessibility_button_targets", "");
   Settings.Secure.putString(getContentResolver(), "accessibility_shortcut_target_service", "");

 
     // ToastUtils.showShort("测试快捷模式打开");
    Settings.Secure.putString(getContentResolver(), "accessibility_button_targets", "com.deling.launcher/com.hrs.tools.services.ToolsAccessibilityService");
    Settings.Secure.putString(getContentResolver(), "accessibility_shortcut_target_service", "com.deling.launcher/com.hrs.tools.services.ToolsAccessibilityService");
             

无障碍服务源码

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

直流电机(二)

直流电机重要参数 直流电机作为一个电磁装置&#xff0c;对于用户来说要哪些参数是他们关注的呢。• 额定功率PN&#xff1a;电机在铭牌规定的额定状态下运行时电机的输出功率(W/kW)• 额定电压UN&#xff1a;电机出线端额定电压(V )• 额定电流IN&#xff1a;电机出线额定电流…

python unittest高级特性!

1. 测试套件 (Test Suites) 测试套件允许你组合多个测试用例&#xff0c;并且能够以不同的方式组织和运行这些测试。这是对测试进行分组和控制测试执行顺序的有效手段。 import unittestclass TestStringMethods(unittest.TestCase): def test_upper(self): self.a…

C语言生成常见波形数据

最近无聊&#xff0c;研究上C语言的一些程序&#xff0c;感觉波形生成还是挺有用的 这里主要生成了正弦&#xff0c;方波&#xff0c;三角波 &#xff0c;锯齿波&#xff0c;指数波形等 首先看看效果&#xff0c; 这里把生成的数据用python画了出来&#xff0c;程序在最后 …

适合母亲节的SVG模版

宝藏模版 往期推荐&#xff08;点击阅读&#xff09;&#xff1a; 趣味效果&#xff5c;高大上&#xff5c;可爱风&#xff5c;年终总结&#xff08;一&#xff09;&#xff5c;年终总结&#xff08;二&#xff09;&#xff5c;循环特效&#xff5c;情人节&#xff08;一&…

[Datawhale AI 夏令营]多模态大模型数据合成赛事-Task2

简单按照datawhale给的task2的文档学习了一下,主要还是学习了Data-Juicer相关的知识。 1.Data-juicer 初探 简单理解一下&#xff0c;Data juicer就是提供给你许多数据处理方法&#xff0c;包括Formatter、Mapper、Filter、Deduplicator和Selector&#xff0c;涉及图像、文本、…

73、 dockerfile

一、dockerfile 自定义镜像---------通过docker创建镜像。 1.1、创建镜像的方式&#xff1a; 1、dockerfile最基的方式&#xff0c;最常用的方式。 2、docker pull 拉取的是最基础的镜像&#xff0c;只有基础功能&#xff0c;没有定制化的功能。 3、基于基础镜像&#xff…

每天五分钟计算机视觉:人脸识别如何解决一次学习的问题?

本文重点 人脸识别技术作为当前计算机技术的重要分支,广泛应用于公共安全、智能家居、金融商业等多个领域。然而,尽管该技术取得了显著进展,但在实际应用中仍面临诸多挑战,其中一次学习问题(One-Shot Learning Problem)尤为突出。 一次学习问题的定义 我们人类是具有快…

单元训练01:LED指示灯的基本控制

蓝桥杯 小蜜蜂 单元训练01&#xff1a;LED指示灯的基本控制 #include "stc15f2k60s2.h" #include <intrins.h>#define LED(x) \{ \P2 P2 & 0x1f | 0x80; \P0 x; \P2 & 0x1f; \}…

用Python实现9大回归算法详解——04. 多项式回归算法

多项式回归 是线性回归的一种扩展&#xff0c;它通过将输入特征的多项式项&#xff08;如平方、立方等&#xff09;引入模型中&#xff0c;以捕捉数据中非线性的关系。虽然多项式回归属于线性模型的范畴&#xff0c;但它通过增加特征的多项式形式&#xff0c;使得模型能够拟合非…

python-NLP:4句法分析

文章目录 句法分析概述句法分析分类句法分析任务 句法结构分析基本概念语法形式化基本方法 依存句法分析浅层句法分析 句法分析概述 句法分析(syntacticparsing)是自然语言处理中的关键技术之一&#xff0c;其基本任务是确定句子的句法结构(syntactic structure)或句子中词汇之…

华三超融合服务器硬件监控指标解读

随着信息技术的快速发展&#xff0c;超融合服务器因其高效、灵活的特点&#xff0c;在企业IT架构中扮演着越来越重要的a角色。华三&#xff08;H3C&#xff09;作为业界知名的网络设备供应商&#xff0c;其超融合服务器产品在市场上广受欢迎。 为了确保这些服务器的稳定运行&am…

asp.net core 调用wps实现word转pdf

安装wps https://www.wps.cn/ 创建.net core控制项目 添加com引用&#xff0c;搜索wps 准备word&#xff0c;名字叫001.docx word转pdf 编写代码 namespace WPSStu01 {internal class Program{static void Main(string[] args){Console.WriteLine("转化开始&q…

JAVA maven pom下载失败问题处理

如果直接在IDEA编辑器中中下载pom依赖 下载失败,可以直接去官网下载jar依赖包(也可以用其他方式,比如找同事拷贝等最终目的是本地需要这个包) 官网点击地址跳转 搜索你需要的包点击进入下载界面 选择对应的版本进行下载 () 下载界面中有对应的当前包的pom坐标个当前jar包 坐…

163邮箱注销后不能再注册

网易邮箱注销后不能再注册 一个手机号只能注册15个163邮箱 再注册会报异常 申请注销邮箱要等15天&#xff0c;才是永久注销 永久注销邮箱后&#xff0c;在拿这个手机号注册新邮箱&#xff0c;还是不行

尊享奢睡新境界:康姿百德柔压磁性枕匠心设计引领品质睡眠革命

重塑睡眠艺术&#xff1a;揭秘康姿百德豪华磁性枕&#xff0c;个性化支撑与卓越透气性的完美融合 在现代家居生活中&#xff0c;细节往往决定了整体的品质。而在睡眠方面&#xff0c;一款好的枕头能够改变我们的睡眠体验。康姿百德柔压磁性枕&#xff08;豪华款&#xff09;正…

Anaconda使用

查看conda版本&#xff1a; conda -V查看支持的cuda版本&#xff1a; nvidia -smi 输出为&#xff1a; Mon Aug 12 12:35:26 2024 ----------------------------------------------------------------------------- | NVIDIA-SMI 528.92 Driver Version: 528.…

string详解(2)— 模拟实现

1.经典的string类实现 最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。 (1) String.h 为了与库里的string进行区分我们使用String&#xff1a; // String.h#pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<stri…

在linux上架设Web服务器Apache(Ubuntu)

欢迎诸位来阅读在下的博文~ 在这里&#xff0c;在下会不定期发表一些浅薄的知识和经验&#xff0c;望诸位能与在下多多交流&#xff0c;共同努力! 江山如画&#xff0c;客心如若&#xff0c;欢迎到访&#xff0c;一展风采 文章目录 背景1. 安装 Apache2. 启动和检查 Apache 服务…

计算机的错误计算(六十三)

摘要 计算机的错误计算&#xff08;五十六&#xff09;探讨了大数的正切函数值的错误计算。本节讨论大数的余切函数的计算精度问题。 例1. 已知 计算 不妨用 3种方法计算。 (1) 在 Python 中利用 直接贴图&#xff1a; (2) 在 Java 中利用 若运行下列代码 import ja…

【Python快速入门和实践016】Python常用脚本-对视频抽取指定帧数并保存

一、功能介绍 这段代码的功能是从一个视频文件中抽取指定数量的帧&#xff0c;并将这些帧保存为图像文件。步骤如下&#xff1a; 设置路径和参数&#xff1a; video_path&#xff1a;视频文件的路径。image_folder&#xff1a;保存抽取图像的目录。num_frames_to_extract&#…