Desde versão 1.6 o Android possui serviço “acessibilidade”. Não é muito difícil de adivinhar para que finalidade ele foi criado mas para nós quem está buscando possibilidades ilimitadas, este serviço é interessante de maneira diferente. Hoje vamos desenvolver um programa que permite monitorar a entrada de dados em outros aplicativos.
Para que serve o serviço de acessibilidade?
Ele permite melhorar interface de aplicativos comuns para ajudar aos usuários com deficiência ou quem temporariamente não pode completamente comunicar com aparelho. Por exemplo, se alguem está dirigindo o carro, quem fica com criança no colo ou fica na festa onde tem muito barulho, ou onde alguem vai precisar algumas interfaces adicionais ou respostas alternativas.
O Android tem um serviço acessibilidade de padrão que chama-se TalkBack. Se é necessário, os desenvolvedores podem implementar seu próprio. Esses serviços tornaram se disponíveis desde época do Android 1.6 (nível 4 de API) e com Android 4.0 (nível 14 de API) eles ganharam melhorias significantes. Essas melhorias foram realizadas através de “biblioteca de suporte” para os aparelhos com versão de API inferior de 14.
Este serviço permite visualizar descrição de todas janelas dos aplicativos que estão rodando e obter os dados digitados pelo usuário (exсeto senhas de acesso, deve concordar que os logins e mensagens de texto em maioria das vezes são suficiente).
Neste artigo eu vou mostrar como implementar serviço de entrada do teclado de maneira mais simples.
Para fazer isso, você tem que criar sucessor para AccessibilityService. No método de conexão onServiceConnected precisamos especificar o filtro de evento (classe AccessibilityServiceInfo) que vai monitorar serviço. E no método onAccessibilityEvent proceder estes eventos. No manifest do aplicativo você deve adicionar as linhas seguintes na parte de descrição de serviço:
<service android:name=".KeyRecordService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> </service>
Se tudo é finalizado corretamente, vamos ver no log alguma coisa tipo isso:
onAccessibilityEvent: [type] TYPE_VIEW_TEXT_CHANGED [class] android.widget.EditText [package] com.android.chrome [time] 113326642 [text] xakep.ru
A classe AccessibilityServiceInfo permite você configurar filtros para aplicativos específicos (que disse “bancos móveis” ou “clientes de redes sociais”?). No evento a gente precisa tirar screenshots. É muito fácil realizar isso no aparelho com root, mas se não tem root, você precisa olhar para as terceiras bibliotecas para tirar screenshots do serviço. Por exemplo, um código para obter screenshot do serviço no aparelho com root:
Process sh = Runtime.getRuntime().exec("su", null, null); OutputStream os = sh.getOutputStream(); os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII")); os.flush(); os.close(); sh.waitFor(); // Então, leia img.png como bitmap e converta o jpg da seguinte maneira Bitmap screen = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + File.separator + "img.png"); // Meu código para salvar ByteArrayOutputStream bytes = new ByteArrayOutputStream(); screen.compress(Bitmap.CompressFormat.JPEG, 15, bytes); // Você pode criar um novo nome de arquivo «test.jpg» na pasta sdcard. File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.jpg"); f.createNewFile(); // Escreva os bytes no arquivo FileOutputStream fo = new FileOutputStream(f); fo.write(bytes.toByteArray()); // Lembre-se de fechar FileOutput fo.close();
Para funcionamento, o serviço exige permissões separadas. O usuário configura isso na parte de configurações “Acessibilidade -> Serviços”.
Executa configurações pelo programa:
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS); startActivityForResult(intent, 0);
Nas versões de Android mais antigas (ainda há muitos desses pelo mundo) usuário pode estar não avisado. Tais direitos podem ser definidos pelo programa:
Settings.Secure.putString(getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "pkgname/classname"); Settings.Secure.putString(getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, "1");
Permissões para manifest:
<uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
Onde pkgname é o nome do seu pacote, classname é o nome da classe de serviço. Nas versões mais recentes do Android, o consentimento do usuário é indispensável.
Conclusão
Do ponto de vista de um programador, os Serviços de acessibilidade permitem expandir um pouco a estrutura estreita de sandbox para interagir com outras aplicativos. O usuário simplesmente pode solicitar acesso aos recursos especiais e, assim, obter acesso aos dados de outros programas. Também vale a pena levar em consideração o serviço TalkBack que visualiza todos os elementos da tela usando a descrição da propriedade contentDescription. O Google dá prioridade ao marketing de mecanismos de pesquisa para aplicativos mais otimizados para o TalkBack.
Como sempre para usuários é aconselhado a pensar três vezes antes de instalar um novo aplicativo, ou, no caso afirmativo, quais permissões a serem atribuídas. Começando com a versão do Android 6.0, isso pode ser realizado de forma mais flexível.