1. Introdução
Os serviços de acessibilidade são um recurso do framework do Android projetado para oferecer feedback de navegação alternativo ao usuário em nome dos aplicativos instalados em dispositivos Android. Um serviço de acessibilidade pode se comunicar com o usuário em nome do aplicativo, por exemplo, convertendo texto em voz ou fornecendo feedback tátil quando um usuário passa o cursor sobre uma área importante da tela. Este codelab mostra como criar um serviço de acessibilidade muito simples.
O que é um serviço de acessibilidade?
Um serviço de acessibilidade ajuda usuários com deficiência a usar dispositivos e apps Android. É um serviço privilegiado de longa duração que ajuda os usuários a processar informações na tela e permite que eles interajam de maneira significativa com um dispositivo.
Exemplos de serviços de acessibilidade comuns
- Acesso com interruptor: permite que usuários do Android com limitações de mobilidade interajam com dispositivos usando um ou mais interruptores.
- Voice Access (Beta): permite que usuários do Android com mobilidade limitada controlem um dispositivo com comandos falados.
- TalkBack: um leitor de tela usados com frequência por pessoas com deficiência visual ou cegas.
Como criar um serviço de acessibilidade
Embora o Google ofereça serviços como o acesso com interruptor, o acesso por voz e o TalkBack para usuários do Android, esses serviços não podem atender a todos os usuários com deficiência. Como muitos usuários com deficiência têm necessidades exclusivas, as APIs do Android para criar serviços de acessibilidade são abertas, e os desenvolvedores podem criar e distribuir esses serviços pela Google Play Store.
O que você vai criar
Neste codelab, você vai desenvolver um serviço simples que faz algumas coisas úteis usando a API Accessibility. Se você souber programar um app Android básico, poderá desenvolver um serviço semelhante.
A API de acessibilidade é poderosa: o código do serviço que você vai criar está contido em apenas quatro arquivos e usa cerca de 200 linhas de código.
O usuário final
Você vai criar um serviço para um usuário hipotético com as seguintes características:
- O usuário tem dificuldade para alcançar os botões laterais de um dispositivo.
- O usuário tem dificuldade para rolar ou deslizar.
Detalhes do serviço
Seu serviço vai sobrepor uma barra de ações global na tela. O usuário pode tocar nos botões dessa barra para realizar as seguintes ações:
- Desligue o dispositivo sem tocar no botão liga/desliga na lateral do smartphone.
- Ajuste o volume sem tocar nos botões na lateral do smartphone.
- Realize ações de rolagem sem rolar a tela.
- Deslize sem precisar usar um gesto de deslizar.
O que é necessário
Neste codelab, vamos usar o seguinte:
- Um computador executando o Android Studio.
- Um terminal para executar comandos simples do shell.
- Um dispositivo com o Android 7.0 (Nougat) conectado ao computador que você vai usar para desenvolvimento.
Vamos começar!
2. Etapas da configuração
Usando o terminal, crie um diretório em que você vai trabalhar. Mude para este diretório.
Fazer o download do código
Clone o repositório que contém o código deste codelab:
git clone https://github.com/android/codelab-android-accessibility.git
O repositório contém vários projetos do Android Studio. No Android Studio, abra GlobalActionBarService.
Clique no ícone do Studio para iniciar o Android Studio:

Selecione a opção Import project (Eclipse ADT, Gradle etc.):

Navegue até o local em que você clonou a origem e selecione GlobalActionBarService.
Em seguida, usando um terminal, mude para o diretório raiz.
3. Entender o código inicial
Explore o projeto que você abriu.
A estrutura básica do serviço de acessibilidade já foi criada para você. Todo o código que você vai escrever neste codelab está restrito aos quatro arquivos a seguir:
- app/src/main/AndroidManifest.xml
- app/src/main/res/layout/action_bar.xml
- app/src/main/res/xml/global_action_bar_service.xml
- app/src/main/java/com/example/android/globalactionbarservice/GlobalActionBarService.java
Confira um tutorial sobre o conteúdo de cada arquivo.
AndroidManifest.xml
As informações sobre o serviço de acessibilidade são declaradas no manifesto:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.globalactionbarservice">
<application>
<service
android:name=".GlobalActionBarService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/global_action_bar_service" />
</service>
</application>
</manifest>
Os três itens obrigatórios a seguir são declarados em AndroidManifest.xml:
- Permissão para usar um serviço de acessibilidade:
<service
...
android:permission = "android.permission.BIND_ACCESSIBILITY_SERVICE">
...
</service>
- A intent AccessibilityService:
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
- Local do arquivo que contém os metadados do serviço que você está criando:
<meta-data
...
android:resource="@xml/global_action_bar_service" />
</service>
global_action_bar_service.xml
Esse arquivo contém os metadados do serviço.
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true" />
Usando um elemento <accessibility-service>, os seguintes metadados foram definidos:
- O tipo de feedback para este serviço. Este codelab usa feedbackGeneric, que é um bom padrão.
- As flags de acessibilidade do serviço. Este codelab usa flags padrão.
- As capacidades necessárias para o serviço:
- Para deslizar, android:canPerformGestures é definido como true.
- Para acessar o conteúdo da janela, android:canRetrieveWindowContent é definido como true.
GlobalActionBarService.java
A maior parte do código do serviço de acessibilidade está em GlobalActionBarService.java. Inicialmente, o arquivo contém o código absoluto mínimo para um serviço de acessibilidade:
- Uma classe que estende AccessibilityService.
- Alguns métodos substituídos obrigatórios (deixados em branco neste codelab).
public class GlobalActionBarService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
}
Você vai adicionar código a esse arquivo durante o codelab.
action_bar.xml
O serviço expõe uma interface com quatro botões, e o arquivo de layout action_bar.xml contém a marcação para mostrar esses botões:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
Por enquanto, esse arquivo contém um LinearLayout vazio. Você vai adicionar marcação aos botões durante o codelab.
Como iniciar o aplicativo
É preciso ter um dispositivo está conectado ao computador. Pressione o ícone verde Play
na barra de menus na parte de cima da tela. Isso vai iniciar o app em que você está trabalhando.
Acesse Configurações > Acessibilidade. O Global Action Bar Service está instalado no seu dispositivo.

Clique em Serviço de barra de ações global e ative-o. A seguinte caixa de diálogo de permissão vai aparecer:

O serviço de acessibilidade pede permissão para observar as ações do usuário, recuperar o conteúdo da janela e realizar gestos em nome do usuário. Ao usar um serviço de acessibilidade de terceiros, confirme se a fonte é confiável.
Executar o serviço não faz muito sentido, já que ainda não adicionamos nenhuma funcionalidade. Vamos começar.
4. Como criar os botões
Abra action_bar.xml em res/layout. Adicione a marcação dentro do LinearLayout atualmente vazio:
<LinearLayout ...>
<Button
android:id="@+id/power"
android:text="@string/power"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/volume_up"
android:text="@string/volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/scroll"
android:text="@string/scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/swipe"
android:text="@string/swipe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Isso cria botões que o usuário pressiona para acionar ações no dispositivo.
Abra GlobalActionBarService.java e adicione uma variável para armazenar o layout da barra de ações:
public class GlobalActionBarService extends AccessibilityService {
FrameLayout mLayout;
...
}
Agora adicione um método onServiceStarted():
public class GlobalActionBarService extends AccessibilityService {
FrameLayout mLayout;
@Override
protected void onServiceConnected() {
// Create an overlay and display the action bar
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
mLayout = new FrameLayout(this);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
lp.format = PixelFormat.TRANSLUCENT;
lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.TOP;
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.action_bar, mLayout);
wm.addView(mLayout, lp);
}
}
O código aumenta o layout e adiciona a barra de ações na parte de cima da tela.
O método onServiceConnected() é executado quando o serviço está conectado. Neste momento, o serviço de acessibilidade tem todas as permissões necessárias para funcionar. A permissão principal que você vai usar aqui é WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY. Essa permissão permite desenhar diretamente na tela acima do conteúdo sem precisar passar por um fluxo de permissões complicado.
Ciclo de vida do serviço de acessibilidade
O ciclo de vida de um serviço de acessibilidade é gerenciado exclusivamente pelo sistema e segue o ciclo de vida estabelecido.
- Um serviço de acessibilidade é iniciado quando o usuário o ativa explicitamente nas configurações do dispositivo.
- Depois que o sistema se vincula a um serviço, ele chama onServiceConnected(). Esse método pode ser substituído por serviços que querem realizar a configuração pós-vinculação.
- Um serviço de acessibilidade é interrompido quando o usuário o desativa nas configurações do dispositivo ou quando ele chama disableSelf().
Como executar o serviço
Antes de iniciar o serviço usando o Android Studio, verifique se as configurações de execução estão configuradas corretamente.
Edite a configuração de execução. Use "Executar" no menu superior e acesse "Editar configurações". Em seguida, usando o menu suspenso, mude a opção de inicialização de "Atividade padrão" para "Nada".

Agora você pode iniciar o serviço usando o Android Studio.
Pressione o ícone verde Play
na barra de menus na parte de cima da tela. Em seguida, acesse Configurações > Acessibilidade e ative o Serviço de barra de ações global.
Os quatro botões que formam a sobreposição da interface do serviço vão aparecer sobre o conteúdo mostrado na tela.

Agora, você vai adicionar funcionalidade aos quatro botões para que um usuário possa tocar neles e realizar ações úteis.
5. Como configurar o botão liga/desliga
Adicione o método configurePowerButton() a GlobalActionBarService.java:
private void configurePowerButton() {
Button powerButton = (Button) mLayout.findViewById(R.id.power);
powerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
performGlobalAction(GLOBAL_ACTION_POWER_DIALOG);
}
});
}
Para acessar o menu do botão liga/desliga, o configurePowerButton() usa o método performGlobalAction(), fornecido por AccessibilityService. O código que você acabou de adicionar é simples: clicar no botão aciona um onClickListener(). Isso chama performGlobalAction(GLOBAL_ACTION_POWER_DIALOG) e mostra a caixa de diálogo de energia ao usuário.
As ações globais não estão vinculadas a nenhuma visualização. Pressionar os botões "Voltar", "Início" ou "Recentes" são outros exemplos de ações globais.
Agora, adicione configurePowerButton() ao fim do método onServiceConnected():
@Override
protected void onServiceConnected() {
...
configurePowerButton();
}
Pressione o ícone verde Play
na barra de menus na parte de cima da tela. Em seguida, acesse Configurações > Acessibilidade e inicie o Serviço da barra de ações global.
Pressione o botão liga/desliga para mostrar a caixa de diálogo de energia.
6. Como configurar o botão de volume
Adicione o método configureVolumeButton() a GlobalActionBarService.java:
private void configureVolumeButton() {
Button volumeUpButton = (Button) mLayout.findViewById(R.id.volume_up);
volumeUpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
}
});
}
O método configureVolumeButton() adiciona um onClickListener() que é acionado quando o usuário pressiona o botão de volume. Dentro desse listener, configureVolumeButton() usa um AudioManager para ajustar o volume do stream.
Qualquer pessoa pode controlar o volume, não é necessário ser um serviço de acessibilidade para isso.
Agora adicione configureVolumeButton() ao final do método onServiceConnected():
@Override
protected void onServiceConnected() {
...
configureVolumeButton();
}
Pressione o ícone verde Play
na barra de menus na parte de cima da tela. Em seguida, acesse Configurações > Acessibilidade e inicie o Serviço de barra de ações global.
Pressione o botão de volume para mudar o volume.
O usuário hipotético que não consegue alcançar os controles de volume na lateral do dispositivo agora pode usar o Serviço de barra de ações global para mudar (aumentar) o volume.
7. Como configurar o botão de rolagem
Esta seção envolve a codificação de dois métodos. O primeiro método encontra um nó rolável, e o segundo realiza a ação de rolagem em nome do usuário.
Adicione o método findScrollableNode a GlobalActionBarService.java:
private AccessibilityNodeInfo findScrollableNode(AccessibilityNodeInfo root) {
Deque<AccessibilityNodeInfo> deque = new ArrayDeque<>();
deque.add(root);
while (!deque.isEmpty()) {
AccessibilityNodeInfo node = deque.removeFirst();
if (node.getActionList().contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD)) {
return node;
}
for (int i = 0; i < node.getChildCount(); i++) {
deque.addLast(node.getChild(i));
}
}
return null;
}
Um serviço de acessibilidade não tem acesso às visualizações reais na tela. Em vez disso, ele vê um reflexo do que está na tela na forma de uma árvore composta por objetos AccessibilityNodeInfo. Esses objetos contêm informações sobre a visualização que representam (localização, texto associado, metadados adicionados para acessibilidade, ações compatíveis etc.). O método findScrollableNode() realiza uma travessia em largura dessa árvore, começando no nó raiz. Se ele encontrar um nó rolável (ou seja, um nó que oferece suporte à ação AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD)), ele o retornará. Caso contrário, retornará nulo.
Agora adicione o método configureScrollButton() a GlobalActionBarService.java:
private void configureScrollButton() {
Button scrollButton = (Button) mLayout.findViewById(R.id.scroll);
scrollButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow());
if (scrollable != null) {
scrollable.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId());
}
}
});
}
Esse método cria um onClickListener() que é acionado quando o botão de rolagem é clicado. Ele tenta encontrar um nó rolável e, se tiver sucesso, realiza a ação de rolagem.
Agora, adicione configureScrollButton() a onServiceConnected():
@Override
protected void onServiceConnected() {
...
configureScrollButton();
}
Pressione o ícone verde Play
na barra de menus na parte de cima da tela. Em seguida, acesse Configurações > Acessibilidade e inicie o Serviço de barra de ações global.
Pressione o botão Voltar para acessar Configurações > Acessibilidade. Os itens na atividade de configurações de acessibilidade podem ser rolados, e tocar no botão "Rolar" realiza uma ação de rolagem. Nosso usuário hipotético que não consegue realizar ações de rolagem com facilidade agora pode usar o botão "Rolar" para rolar uma lista de itens.
8. Como configurar o botão de deslizar
Adicione o método configureSwipeButton() a GlobalActionBarService.java:
private void configureSwipeButton() {
Button swipeButton = (Button) mLayout.findViewById(R.id.swipe);
swipeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Path swipePath = new Path();
swipePath.moveTo(1000, 1000);
swipePath.lineTo(100, 1000);
GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
gestureBuilder.addStroke(new GestureDescription.StrokeDescription(swipePath, 0, 500));
dispatchGesture(gestureBuilder.build(), null, null);
}
});
}
O método configureSwipeButton() usa uma nova API adicionada no N que realiza gestos em nome do usuário. O código usa um objeto GestureDescription para especificar o caminho do gesto a ser realizado (valores codificados são usados neste codelab) e envia o gesto de deslizar em nome do usuário usando o método dispatchGesture() do AccessibilityService.
Agora, adicione configureSwipeButton() a onServiceConnected():
@Override
protected void onServiceConnected() {
...
configureSwipeButton();
}
Pressione o ícone verde Play
na barra de menus na parte de cima da tela. Em seguida, acesse Configurações > Acessibilidade e inicie o Serviço de barra de ações global.
A maneira mais fácil de testar a funcionalidade de deslizar é abrir o aplicativo Maps instalado no seu smartphone. Quando o mapa é carregado, tocar no botão "Deslizar" desliza a tela para a direita.
9. Resumo
Parabéns! Você criou um serviço de acessibilidade simples e funcional.
É possível estender esse serviço de várias maneiras. Exemplo:
- Faça com que a barra de ações possa ser movida (por enquanto, ela fica na parte de cima da tela).
- Permitir que o usuário aumente e diminua o volume.
- Permite que o usuário deslize para a esquerda e para a direita.
- Adiciona suporte para outros gestos que a barra de ações pode responder.
Este codelab aborda apenas um pequeno subconjunto da funcionalidade fornecida pelas APIs de acessibilidade. A API também abrange o seguinte (lista parcial):
- Suporte a várias janelas.
- Suporte para AccessibilityEvents. Quando a interface muda, os serviços de acessibilidade são notificados sobre essas mudanças usando objetos AccessibilityEvent. O serviço pode responder de acordo com as mudanças na interface.
- Capacidade de controlar a ampliação.
Este codelab ensina a escrever um serviço de acessibilidade. Se você conhece um usuário com problemas específicos de acessibilidade que gostaria de resolver, agora é possível criar um serviço para ajudar essa pessoa.