Aviso: violação do Google Play
O Google ameaçou remover aplicativos da Play Store se eles usassem serviços de acessibilidade para fins de não acessibilidade. No entanto, isso está sendo reconsiderado .
Benefícios
- Testado e funcionando no Android 2.2 (API 8) através do Android 7.1 (API 25).
- Não requer pesquisa.
- Não requer a
GET_TASKS
permissão.
Desvantagens
- Cada usuário deve ativar o serviço nas configurações de acessibilidade do Android.
- Isso não é 100% confiável. Ocasionalmente, os eventos ocorrem fora de ordem.
- O serviço está sempre em execução.
- Quando um usuário tenta ativar
AccessibilityService
, ele não pode pressionar o botão OK se um aplicativo tiver colocado uma sobreposição na tela. Alguns aplicativos que fazem isso são Velis Auto Brightness e Lux. Isso pode ser confuso porque o usuário pode não saber por que não pode pressionar o botão ou como contornar esse problema.
- Eles
AccessibilityService
não conhecerão a atividade atual até a primeira alteração de atividade.
Exemplo
Serviço
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
Mesclar isso em seu manifesto:
<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>
Informações de serviço
Coloque isso em 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"/>
Habilitando o serviço
Cada usuário do aplicativo precisará ativar explicitamente o AccessibilityService
para que ele seja usado. Veja esta resposta StackOverflow para saber como fazer isso.
Observe que o usuário não poderá pressionar o botão OK ao tentar ativar o serviço de acessibilidade se um aplicativo tiver colocado uma sobreposição na tela, como Velis Auto Brightness ou Lux.