在Android设备上以编程方式启用/禁用辅助功能设置

在Android设备上以编程方式启用/禁用辅助功能设置,android,accessibility,kiosk,Android,Accessibility,Kiosk,如何以编程方式启用/禁用android屏幕阅读器服务,如TalkBack 我正在开发一个信息亭类型的应用程序,它将安装在一个安卓设备上,当参观者参观某个特定的博物馆时,该设备将借给他们。(我们仍在决定使用什么设备。)计划只允许用户使用我们的应用程序,而不允许用户访问android设置应用程序。但是,我们希望允许用户配置一些辅助功能设置。当他们使用完设备后,我们需要将所有设置恢复为默认设置 下面链接中的讨论有很多建议,建议启动Android的设置应用程序。但我们不希望用户访问许多其他设置 只有系统

如何以编程方式启用/禁用android屏幕阅读器服务,如TalkBack

我正在开发一个信息亭类型的应用程序,它将安装在一个安卓设备上,当参观者参观某个特定的博物馆时,该设备将借给他们。(我们仍在决定使用什么设备。)计划只允许用户使用我们的应用程序,而不允许用户访问android设置应用程序。但是,我们希望允许用户配置一些辅助功能设置。当他们使用完设备后,我们需要将所有设置恢复为默认设置

下面链接中的讨论有很多建议,建议启动Android的设置应用程序。但我们不希望用户访问许多其他设置


只有系统应用程序可以通过编程方式启用/禁用辅助功能服务。 系统应用程序可以直接写入设置安全数据库以启动辅助功能服务

Settings.Secure.putString(getContentResolver(),Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "com.packagename/com.packagename.componentname");
在安全数据库中写入设置需要以下权限:

<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
从棒棒糖你不能改变所有的设置,打破安全 政策。其中一些您可以访问,但必须获得许可 为此。所以请不要在这上面浪费时间


我认为有一种方法可以做到这一点,如果你让你的应用成为一个
可访问性服务
(但你必须在安装后手动启用它)

然后,在AccessibilityService类中,在AccessibilityEvent方法中,您可以浏览视图(递归)并执行单击-在下面的示例中,它将单击设置中的对讲项-然后它应该在下一个屏幕上切换切换按钮(诀窍是您可以单击父视图,而不是切换视图本身)-我没有尝试过此代码:)


您的应用程序是否将被签署为系统应用程序?可能是。这是必要的,让这项工作?检查这另一个帖子了StackOverflow,嗨约翰,你有任何解决方案,我也在寻找同样的事情。如果你得到了解决方案,那么请发布你的Ansauj,我的计划是让一个系统签名的应用程序声明WRITE_SECURE_SETTINGS权限,以便我可以使用SETTINGS.SECURE.putString更新必要的设置。通过将SETTINGS.SECURE.ACCESSIBILITY_启用为1或0,我可以让我的系统签名应用程序启用/禁用对讲。但是,当我通过将对讲设置为0来禁用对讲时,会显示一个错误,显示“不幸的是,Pico TTS已停止”。有人对如何防止显示该错误消息有任何建议吗?首先从Settings.Secure.ENABLED\u ACCESSIBILITY\u SERVICES中删除对讲条目,然后将ACCESSIBILITY\u ENABLED更新为0I仍会收到相同的错误。然而,我注意到标准的Android设置应用程序也发生了同样的事情。所以我认为这个错误与我安装的TalkBack版本有关。我希望,一旦我得到了我将使用的实际设备,这将不会成为一个问题。我认为问题是对讲可访问性服务并没有正确关闭tts
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    AccessibilityNodeInfo source = event.getSource();        
    if(event.getEventType()==AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) 
        explore(source);

}

private void explore(AccessibilityNodeInfo view){
    int count = view.getChildCount();
    for(int i=0; i<count; i++){
        AccessibilityNodeInfo child = view.getChild(i);
        if(!MODE_TALK_BACK_SCREEN){
            if(child.getText()!=null && child.getText().toString().toLowerCase().contains("TalkBack")){
                child.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
                MODE_TALK_BACK_SCREEN=true;
                return;
            }
        }else{
            if("ToggleButton".equals(child.getClassName().toString())){ //there ony one toggle button on the screen
                child.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
                performGlobalAction(GLOBAL_ACTION_BACK);
                performGlobalAction(GLOBAL_ACTION_BACK);//need to go back two time - i don't know if that will work :)
                return;
            }
        }
        explore(child);
        child.recycle();
    }
<accessibility-service     xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/accessibility_service_description"
android:packageNames="com.android.settings"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFlags="flagDefault"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity"
/>