Advertencia: violación de Google Play
Google ha amenazado con eliminar aplicaciones de Play Store si usan servicios de accesibilidad para fines de no accesibilidad. Sin embargo, se informa que esto se está reconsiderando .
Beneficios
- Probado y funcionando en Android 2.2 (API 8) a través de Android 7.1 (API 25).
- No requiere sondeo.
- No requiere el
GET_TASKS
permiso.
Desventajas
- Cada usuario debe habilitar el servicio en la configuración de accesibilidad de Android.
- Esto no es 100% confiable. Ocasionalmente los eventos están fuera de servicio.
- El servicio siempre se está ejecutando.
- Cuando un usuario intenta habilitar
AccessibilityService
, no puede presionar el botón Aceptar si una aplicación ha colocado una superposición en la pantalla. Algunas aplicaciones que hacen esto son Velis Auto Brightness y Lux. Esto puede ser confuso porque el usuario puede no saber por qué no puede presionar el botón o cómo solucionarlo.
- El
AccessibilityService
no sabrá la actividad actual hasta el primer cambio de actividad.
Ejemplo
Servicio
public class WindowChangeDetectingService extends AccessibilityService {
@Override
protected void onServiceConnected() {
super.onServiceConnected();
//Configure these here for compatibility with API 13 and below.
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(config);
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
if (event.getPackageName() != null && event.getClassName() != null) {
ComponentName componentName = new ComponentName(
event.getPackageName().toString(),
event.getClassName().toString()
);
ActivityInfo activityInfo = tryGetActivity(componentName);
boolean isActivity = activityInfo != null;
if (isActivity)
Log.i("CurrentActivity", componentName.flattenToShortString());
}
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public void onInterrupt() {}
}
AndroidManifest.xml
Combina esto en tu manifiesto:
<application>
<service
android:label="@string/accessibility_service_name"
android:name=".WindowChangeDetectingService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibilityservice"/>
</service>
</application>
Información de servicio
Pon esto en res/xml/accessibilityservice.xml
:
<?xml version="1.0" encoding="utf-8"?>
<!-- These options MUST be specified here in order for the events to be received on first
start in Android 4.1.1 -->
<accessibility-service
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews"
android:description="@string/accessibility_service_description"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="UnusedAttribute"/>
Habilitar el servicio
Cada usuario de la aplicación deberá habilitar explícitamente el AccessibilityService
para que pueda ser utilizado. Ver esta respuesta de StackOverflow para cómo hacer esto.
Tenga en cuenta que el usuario no podrá presionar el botón Aceptar cuando intente habilitar el servicio de accesibilidad si una aplicación ha colocado una superposición en la pantalla, como Velis Auto Brightness o Lux.