我正在开发一个使用TalkBack引导用户的应用程序。但是,在这种情况下,我希望在应用程序布局中有一些细微的差异,以便更容易进行导航,并且具有额外的语音输出(使用TextToSpeech)来帮助指导用户。
我的问题是,仅当用户激活TalkBack时,才想要这些更改和额外的输出。
有没有办法知道是否已经激活了TalkBack?我没有找到直接访问TalkBack设置的特定信息,但我希望能够访问通用手机设置,以便了解我所需要的内容。
我正在开发一个使用TalkBack引导用户的应用程序。但是,在这种情况下,我希望在应用程序布局中有一些细微的差异,以便更容易进行导航,并且具有额外的语音输出(使用TextToSpeech)来帮助指导用户。
我的问题是,仅当用户激活TalkBack时,才想要这些更改和额外的输出。
有没有办法知道是否已经激活了TalkBack?我没有找到直接访问TalkBack设置的特定信息,但我希望能够访问通用手机设置,以便了解我所需要的内容。
推荐的方法是查询AccessibilityManager
以获取辅助功能服务的启用状态。
AccessibilityManager am = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE);
boolean isAccessibilityEnabled = am.isEnabled();
boolean isExploreByTouchEnabled = am.isTouchExplorationEnabled();
您可以像这样在Kotlin中创建内联函数:
fun Context.isScreenReaderOn():Boolean{
val am = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
if (am != null && am.isEnabled) {
val serviceInfoList =
am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN)
if (!serviceInfoList.isEmpty())
return true
}
return false}
然后您只需在需要时调用它,如下所示:
if(context.isScreenReaderOn()){
...
}
目前经过测试并且运作良好。
val Context.isScreenReaderOn: Boolean get() { val am = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager if (am.isEnabled) { val serviceInfoList = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN) if (serviceInfoList.isNotEmpty()) return true } return false }
- latssonAccessibilityServices services = AccessibilityServices.newInstance(context);
services.isSpokenFeedbackEnabled();
public boolean isSpokenFeedbackEnabled() {
List<AccessibilityServiceInfo> enabledServices = getEnabledServicesFor(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
return !enabledServices.isEmpty();
}
private List<AccessibilityServiceInfo> getEnabledServicesFor(int feedbackTypeFlags) {
return accessibilityManager.getEnabledAccessibilityServiceList(feedbackTypeFlags);
}
举个例子,看一下Eyes-Free shell应用程序中HomeLauncher.java文件中的isScreenReaderActive()
(通过groups thread)。
总之:您可以使用Intents检测所有屏幕阅读器,然后查询每个提供程序的状态以查看其是否处于活动状态。
如果您真的想将其限制为仅TalkBack,则可以尝试检查queryIntentServices()
返回的每个结果的ResolveInfo.serviceInfo.packageName
,以查看它是否与TalkBack包匹配。
如果您正在使用Compose进行编程,可以在Context上添加此实用工具扩展:
@Composable
internal fun Context.collectIsTalkbackEnabledAsState(): State<Boolean> {
val accessibilityManager =
this.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager?
fun isTalkbackEnabled(): Boolean {
val accessibilityServiceInfoList =
accessibilityManager?.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN)
return accessibilityServiceInfoList?.any {
it.resolveInfo.serviceInfo.processName.equals(TALKBACK_PACKAGE_NAME)
} ?: false
}
val talkbackEnabled = remember { mutableStateOf(isTalkbackEnabled()) }
val accessibilityManagerEnabled = accessibilityManager?.isEnabled ?: false
var accessibilityEnabled by remember { mutableStateOf(accessibilityManagerEnabled) }
accessibilityManager?.addAccessibilityStateChangeListener { accessibilityEnabled = it }
LaunchedEffect(accessibilityEnabled) {
talkbackEnabled.value = if (accessibilityEnabled) isTalkbackEnabled() else false
}
return talkbackEnabled
}
private const val TALKBACK_PACKAGE_NAME = "com.google.android.marvin.talkback"
然后在目标组合中使用它:
@Composable
fun SomeComposable() {
val talkbackEnabled by LocalContext.current.collectIsTalkbackEnabledAsState()
if (talkbackEnabled) {
/** do something here **/
}
}
AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
if (am != null && am.isEnabled()) {
List<AccessibilityServiceInfo> serviceInfoList = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
if (!serviceInfoList.isEmpty())
return true;
}
return false;
对于我来说,我是通过以下方式解决了这个问题,在我的项目中它很好用:
下面是详细代码:
private static final String TALKBACK_SETTING_ACTIVITY_NAME = "com.android.talkback.TalkBackPreferencesActivity";
public static boolean accessibilityEnable(Context context) {
boolean enable = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
try {
AccessibilityManager manager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
List<AccessibilityServiceInfo> serviceList = manager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
for (AccessibilityServiceInfo serviceInfo : serviceList) {
String name = serviceInfo.getSettingsActivityName();
if (!TextUtils.isEmpty(name) && name.equals(TALKBACK_SETTING_ACTIVITY_NAME)) {
enable = true;
}
}
} catch (Exception e) {
if (Logging.isDebugLogging()) {
e.printStackTrace();
}
}
}
return enable;
}
accessibilityServiceInfo.getResolveInfo().serviceInfo.processName
检查 Android 辅助功能套件的包名,而不是它的名称。 - Jaco/**
* This method checks if Google Talkback is enabled by using the [accessibilityManager]
*/
private fun isGoogleTalkbackActive(accessibilityManager : AccessibilityManager) : Boolean
{
val accessibilityServiceInfoList = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN)
for (accessibilityServiceInfo in accessibilityServiceInfoList)
{
if ("com.google.android.marvin.talkback".equals(accessibilityServiceInfo.resolveInfo.serviceInfo.processName))
{
return true
}
}
return false
}
记得将Google URI注册为常量,并像@caseyburkhardt所说获取Accessibility Manager实例(https://dev59.com/tm435IYBdhLWcg3w9FBY#12362545)。与@david-z的答案不同之处在于,我获取了Android Accessibility Suite包名而不是其应用程序名称,因为这样更加安全。如果您想在此检查后查看是否启用了其他辅助功能套件(例如三星屏幕阅读器),可以检查if (accessibilityManager.isTouchExplorationEnabled)
干杯!
打开系统设置,进入辅助功能,关闭Talk back选项
TalkBack
是否处于激活状态。 - adiga
isTouchExplorationEnabled()
是否仍然返回true? - ataulmam.isTouchExplorationEnabled()
。(如果“选择以发言”已启用但未启用TalkBack,am.isEnabled()
仍将返回true。) - Jonik