O segundo Visualização do Desenvolvedor do Android 11 já está disponível, teste e compartilhe seu feedback.

Otimizar seu app para o preenchimento automático

Os aplicativos que usam visualizações padrão funcionam com a estrutura de preenchimento automático sem necessidade de nenhuma configuração especial. No entanto, é possível otimizar a forma como seu app funciona com essa estrutura. Para ver um tutorial guiado, consulte o codelab Otimizar seu app para preenchimento automático (link em inglês).

Configurar o ambiente de preenchimento automático

Esta seção descreve como configurar a funcionalidade básica de preenchimento automático para seu app.

Configurar um serviço de preenchimento automático

É necessário configurar um serviço de preenchimento automático no seu dispositivo para que o app use a estrutura de preenchimento automático. Embora a maior parte dos smartphones e tablets com Android 8.0 (APU de nível 26) ou versões mais recentes tenha um serviço de preenchimento automático, recomendamos que você use um serviço de teste ao testar seu app, como o serviço de preenchimento automático do Exemplo de estrutura de preenchimento automático do Android. Ao usar um emulador, é necessário configurar explicitamente um serviço de preenchimento automático, porque ele pode não ter um serviço padrão.

Depois de instalar o serviço de preenchimento automático de teste do app de exemplo, ative-o navegando para Config. > Sistema > Idioma e entrada > Avançado > Assistência de entrada > Serviço de preenchimento automático.

Para ver mais informações sobre como configurar um emulador para testar o preenchimento automático, consulte Testar seu app com preenchimento automático.

Dar dicas para o preenchimento automático

O serviço de preenchimento automático tenta determinar o tipo de visualização usando heurística. No entanto, caso seu app dependa dessas heurísticas, o comportamento de preenchimento automático poderá mudar inesperadamente quando o app for atualizado. Para garantir que o serviço de preenchimento automático identifique corretamente os formatos do seu app, você precisa dar dicas de preenchimento automático.

Você pode configurar essas dicas usando o atributo android:autofillHints. O exemplo a seguir configura uma dica de "senha" no EditText:

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:autofillHints="password" />
    

Você também pode definir dicas de forma programática usando o método setAutofillHints(), conforme mostrado no exemplo a seguir:

Kotlin

    val password = findViewById<EditText>(R.id.password)
    password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)
    

Java

    EditText password = findViewById(R.id.password);
    password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);
    

Constantes de dicas predefinidas

A estrutura de preenchimento automático não valida dicas. Elas são apenas passadas sem alteração ou validação para o serviço de preenchimento automático. Embora seja possível usar qualquer valor, a classe View e a classe AndroidX HintConstants contêm listas de constantes de dica com compatibilidade oficial.

Ao usar uma combinação dessas constantes, é possível criar layouts para situações comuns de preenchimento automático:

Credenciais da conta

Ao preencher automaticamente as credenciais da conta, um formulário de login pode incluir dicas como AUTOFILL_HINT_USERNAME e AUTOFILL_HINT_PASSWORD.

Ao criar uma nova conta ou quando os usuários alterarem o nome de usuário e a senha, você poderá usar AUTOFILL_HINT_NEW_USERNAME e AUTOFILL_HINT_NEW_PASSWORD.

Informações do cartão de crédito

Ao solicitar informações de cartão de crédito, você pode usar dicas como AUTOFILL_HINT_CREDIT_CARD_NUMBER e AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE.

Para datas de validade do cartão de crédito, siga um destes procedimentos:

Endereço físico

Ao realizar o preenchimento automático de um endereço físico, você pode usar dicas como as seguintes:

Nomes de pessoas

Ao realizar o preenchimento automático de nomes de pessoas, você pode usar dicas como as seguintes:

Números de telefone

Para números de telefone, você pode usar o seguinte:

Senha única (OTP, na sigla em inglês)

Para uma senha única em uma única visualização, você pode usar AUTOFILL_HINT_SMS_OTP.

Ao usar várias visualizações em que cada uma delas mapeia um único dígito da OTP, você pode usar o método generateSmsOptHintForCharacterPosition() para gerar dicas por caractere.

Marcar campos como importantes para o preenchimento automático

Você pode informar ao sistema se os campos do seu app precisam ser incluídos em uma estrutura de visualização para fins de preenchimento automático. Por padrão, a visualização usa o modo IMPORTANT_FOR_AUTOFILL_AUTO, que permite que o Android use a heurística dele para determinar se a visualização é importante para o preenchimento automático.

Você pode definir a importância usando o atributo android:importantForAutofill:

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:importantForAutofill="no" />
    

O valor de importantForAutofill pode ser qualquer um dos valores definidos em android:importantForAutofill:

auto
Permite que o sistema Android use a heurística dele para determinar se a visualização é importante para o preenchimento automático.
no
Essa visualização não é importante para o preenchimento automático.
noExcludeDescendants
Essa visualização e as filhas dela não são importantes para o preenchimento automático.
yes
Essa visualização é importante para o preenchimento automático.
yesExcludeDescendants
Essa visualização é importante para o preenchimento automático, mas os filhos dela não são.

Você também pode usar o método setImportantForAutofill():

Kotlin

    val captcha = findViewById<TextView>(R.id.captcha)
    captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO)
    

Java

    TextView captcha = findViewById(R.id.captcha);
    captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
    

Há casos em que uma visualização, uma estrutura de visualização ou toda a atividade não é importante para o preenchimento automático:

  • Um campo CAPTCHA em uma atividade de login geralmente não é importante para o preenchimento automático. Em casos como esse, você pode marcar a visualização como IMPORTANT_FOR_AUTOFILL_NO.
  • Em uma visualização em que o usuário cria conteúdo, como um editor de texto ou planilhas, a estrutura inteira da visualização geralmente não é importante para o preenchimento automático. Em casos como esse, você pode marcar a visualização como IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS para garantir que todos os filhos também sejam marcados como não importantes para preenchimento automático.
  • Em algumas atividades dentro de jogos, como aquelas que exibem jogabilidade, nenhuma das visualizações das atividades é importante para o preenchimento automático. Você pode marcar a visualização raiz como IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS para garantir que todas as visualizações da atividade sejam marcadas como não importantes para o preenchimento automático.

Associar dados de sites com apps para dispositivos móveis

Serviços de preenchimento automático, como o Preenchimento automático do Google, podem compartilhar dados de login de usuários entre navegadores e dispositivos Android após a associação do app com o site. Quando um usuário escolhe o mesmo serviço de preenchimento automático em ambas as plataformas, o login no app da Web disponibiliza as credenciais para o preenchimento automático quando ele faz login no app para Android correspondente.

Para associar seu app para Android com seu site, é necessário hospedar um Link de recursos digitais com a relação delegate_permission/common.get_login_creds no site. Em seguida, declare a associação no arquivo AndroidManifest.xml do seu app. Para ver instruções detalhadas de como associar seu site ao seu app para Android, consulte Ativar o login automático em apps e sites.

Preencher um fluxo de trabalho de preenchimento automático

Esta seção descreve situações específicas em que você pode seguir etapas para melhorar a funcionalidade de preenchimento automático para os usuários do seu app.

Determinar se o preenchimento automático está ativado

Você pode implementar uma funcionalidade de preenchimento automático adicional no seu app ou até mesmo em visualizações específicas do app, caso o preenchimento automático esteja disponível para o usuário. Por exemplo, TextView mostra uma entrada de preenchimento automático no menu flutuante se o preenchimento automático estiver ativado para o usuário. Para verificar se o preenchimento automático está ativado, chame o método isEnabled() do objeto AutofillManager.

Os usuários podem ativar ou desativar o preenchimento automático e alterar esse serviço navegando até Config. > Sistema > Idioma e entrada > Avançado > Assistência de entrada > Serviço de preenchimento automático . Seu app não pode modificar as configurações de preenchimento automático do usuário.

Para garantir que sua experiência de assinatura e login seja otimizada para usuários sem preenchimento automático, considere a implementação do Smart Lock para senhas.

Forçar uma solicitação de preenchimento automático

Às vezes, pode ser necessário forçar uma solicitação de preenchimento automático, que ocorre em resposta a uma ação do usuário. Por exemplo, TextView oferece um item de menu de preenchimento automático quando o usuário toca em uma visualização e a mantém pressionada. O exemplo de código a seguir mostra como forçar uma solicitação de preenchimento automático:

Kotlin

    fun eventHandler(view: View) {
        val afm = requireContext().getSystemService(AutofillManager::class.java)
        afm?.requestAutofill(view)
    }
    

Java

    public void eventHandler(View view) {
        AutofillManager afm = context.getSystemService(AutofillManager.class);
        if (afm != null) {
            afm.requestAutofill(view);
        }
    }
    

Também é possível usar o método cancel() para cancelar o contexto atual de preenchimento automático. Isso pode ser útil, por exemplo, se você tem um botão que limpa os campos em uma página de login.

Usar o tipo de preenchimento automático correto para dados nos controles do seletor

Os seletores são úteis em algumas situações de preenchimento automático, porque fornecem uma IU que permite que os usuários alterem o valor de um campo que armazena dados de data ou hora. Por exemplo, em um formulário de cartão de crédito, um seletor de data permite que os usuários insiram ou alterem a data de validade do cartão de crédito. No entanto, você precisará usar outra visualização, como EditText, para exibir os dados quando o seletor não estiver visível.

Um objeto EditText nativamente espera o preenchimento automático de dados do tipo AUTOFILL_TYPE_TEXT. Caso esteja usando outro tipo de dados, é necessário criar uma visualização personalizada, herdada de EditText e que implemente os métodos necessários para processar o tipo de dados correspondente. Por exemplo, caso você tenha um campo de data, implemente os métodos com uma lógica que processe corretamente os valores do tipo AUTOFILL_TYPE_DATE.

Quando você especifica o tipo de dados de preenchimento automático, esse serviço pode criar uma representação apropriada dos dados exibidos na visualização. Para ver mais informações, consulte Como usar seletores com o preenchimento automático.

Concluir o contexto de preenchimento automático

A estrutura de preenchimento automático salva a entrada do usuário para uso futuro mostrando uma caixa de diálogo "Salvar para preenchimento automático?" depois que o contexto do preenchimento é concluído. Normalmente, o contexto do preenchimento automático termina quando uma atividade é concluída. No entanto, há algumas situações em que você precisa notificar explicitamente a estrutura; por exemplo, caso esteja usando a mesma atividade, mas fragmentos diferentes para suas telas de login e de conteúdo. Nessas situações especiais, você pode concluir o contexto explicitamente chamando AutofillManager.commit().

Compatibilidade com visualizações personalizadas

As visualizações personalizadas podem especificar os metadados que são expostos à estrutura de preenchimento automático usando a API de preenchimento automático. Algumas visualizações agem como um contêiner de filhos virtuais, como visualizações que contêm IU renderizada por OpenGL. Essas visualizações precisam usar a API para especificar a estrutura das informações usadas no app antes de funcionar com a estrutura de preenchimento automático.

Se seu app usa visualizações personalizadas, considere os seguintes cenários:

  • A visualização personalizada fornece uma estrutura de visualização padrão ou uma estrutura de visualização comum.
  • A visualização personalizada tem uma estrutura virtual ou uma estrutura de visualização que não está disponível para a estrutura de preenchimento automático.

Visualizações personalizadas com estrutura de visualização padrão

As visualizações personalizadas podem definir os metadados necessários para que o preenchimento automático funcione. Verifique se a visualização personalizada gera os metadados de forma adequada para funcionar com a estrutura de preenchimento automático. Sua visualização personalizada precisa executar as seguintes ações:

  • Manipular o valor do preenchimento automático que a estrutura envia para seu app.
  • Fornecer o tipo e o valor do preenchimento automático para a estrutura.

Quando o preenchimento automático é acionado, a estrutura de preenchimento automático chama autofill() na sua visualização e envia o valor que a visualização da propriedade precisa usar. Você precisa implementar autofill() para especificar como a visualização personalizada processa o valor do preenchimento automático.

Sua visualização precisa especificar um tipo e um valor de preenchimento automático substituindo os métodos getAutofillType() e getAutofillValue(), respectivamente. Ao adicionar esse código, você garante que sua visualização possa fornecer tipos e valores de preenchimento automático adequados à estrutura.

Por fim, o preenchimento automático não pode preencher a visualização caso o usuário não possa fornecer um valor para a visualização no estado atual (por exemplo, se a visualização estiver desativada). Nesses casos, getAutofillType() retorna AUTOFILL_TYPE_NONE, getAutofillValue() retorna null e autofill() não faz nada.

Os casos a seguir exigem outras etapas para que possam funcionar corretamente na estrutura:

  • A visualização personalizada é editável.
  • A visualização personalizada contém dados confidenciais.

A visualização personalizada é editável.

Se a visualização for editável, você precisará notificar a estrutura de preenchimento automático sobre as alterações chamando notifyValueChanged() no objeto AutofillManager.

A visualização personalizada contém dados confidenciais

Caso a visualização contenha informações de identificação pessoal, como endereços de e-mail, números de cartão de crédito e senhas, ela precisará ser marcada como tal. Em geral, as visualizações cujo conteúdo é proveniente de recursos estáticos não contêm dados confidenciais, mas aquelas cujo conteúdo é definido de modo dinâmico podem conter dados confidenciais. Por exemplo, um rótulo que contenha digite seu nome de usuário não contém dados confidenciais, enquanto um rótulo que contenha Olá, João, sim. Para marcar se a visualização contém dados confidenciais ou não, implemente onProvideAutofillStructure() e chame setDataIsSensitive() no objeto ViewStructure.

O exemplo de código a seguir mostra como marcar os dados na estrutura da visualização como confidenciais ou não:

Kotlin

    override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) {
        super.onProvideAutofillStructure(structure, flags)

        // Content that comes from static resources generally isn't sensitive.
        val sensitive = !contentIsSetFromResources()
        structure.setDataIsSensitive(sensitive)
    }
    

Java

    @Override
    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
        super.onProvideAutofillStructure(structure, flags);

        // Content that comes from static resources generally isn't sensitive.
        boolean sensitive = !contentIsSetFromResources();
        structure.setDataIsSensitive(sensitive);
    }
    

Se a visualização aceita apenas valores predefinidos, use o método setAutofillOptions() para definir as opções que podem ser usadas para o preenchimento automático dessa visualização. Especificamente, as visualizações cujo tipo de preenchimento automático é AUTOFILL_TYPE_LIST precisam usar esse método porque o serviço de preenchimento automático pode realizar um trabalho melhor se conhecer as opções disponíveis para preencher a visualização.

As visualizações que usam um adaptador, como um Spinner, são um caso parecido. Por exemplo, um controle giratório que fornece anos criados dinamicamente (com base no ano atual) para usar em campos de validade de cartão de crédito pode implementar o método getAutofillOptions() da interface Adapter para fornecer uma lista de anos.

Visualizações que usam um ArrayAdapter também podem fornecer listas de valores. ArrayAdapter define automaticamente as opções de preenchimento automático para recursos estáticos. No entanto, se você fornecer os valores de maneira dinâmica, precisará substituir getAutofillOptions().

Visualizações personalizadas com estrutura virtual

A estrutura de preenchimento automático exige uma estrutura de visualização para que possa editar e salvar as informações na IU do seu app. Existem algumas situações em que a estrutura de visualização não está disponível para a estrutura:

  • O app usa um mecanismo de renderização de nível inferior, como OpenGL, para renderizar a IU.
  • O app usa uma instância de Canvas para desenhar a IU.

Nesses casos, você pode especificar uma estrutura de visualização implementando onProvideAutofillVirtualStructure() e seguindo estas etapas:

  1. Aumente a contagem de filhos da estrutura de visualização chamando addChildCount().
  2. Adicione uma filha chamando newChild().
  3. Defina o ID de preenchimento automático da filha chamando setAutofillId().
  4. Defina as propriedades relevantes, como o valor e o tipo de preenchimento automático.
  5. Se os dados da filha virtual forem confidenciais, será necessário passar true para setDataIsSensitive(), ou false, caso não forem.

O snippet de código a seguir mostra como criar uma nova filha na estrutura virtual:

Kotlin

    override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) {

        super.onProvideAutofillVirtualStructure(structure, flags)

        // Create a new child in the virtual structure.
        structure.addChildCount(1)
        val child = structure.newChild(childIndex)

        // Set the autofill ID for the child.
        child.setAutofillId(structure.autofillId!!, childVirtualId)

        // Populate the child by providing properties such as value and type.
        child.setAutofillValue(childAutofillValue)
        child.setAutofillType(childAutofillType)

        // Some children can provide a list of values. For example, if the child is
        // a spinner.
        val childAutofillOptions = arrayOf<CharSequence>("option1", "option2")
        child.setAutofillOptions(childAutofillOptions)

        // Just like other types of views, mark the data as sensitive, if
        // appropriate.
        val sensitive = !contentIsSetFromResources()
        child.setDataIsSensitive(sensitive)
    }
    

Java

    @Override
    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {

        super.onProvideAutofillVirtualStructure(structure, flags);

        // Create a new child in the virtual structure.
        structure.addChildCount(1);
        ViewStructure child =
                structure.newChild(childIndex);

        // Set the autofill ID for the child.
        child.setAutofillId(structure.getAutofillId(), childVirtualId);

        // Populate the child by providing properties such as value and type.
        child.setAutofillValue(childAutofillValue);
        child.setAutofillType(childAutofillType);

        // Some children can provide a list of values. For example, if the child is
        // a spinner.
        CharSequence childAutofillOptions[] = { "option1", "option2" };
        child.setAutofillOptions(childAutofillOptions);

        // Just like other types of views, mark the data as sensitive, if
        // appropriate.
        boolean sensitive = !contentIsSetFromResources();
        child.setDataIsSensitive(sensitive);
    }
    

Quando os elementos em uma estrutura virtual mudam, é necessário notificar a estrutura realizando as seguintes tarefas:

  • Se o foco dentro das filhas mudou , chame notifyViewEntered() e notifyViewExited() no objeto AutofillManager.
  • Se o valor de uma filha mudou, chame notifyValueChanged() no objeto AutofillManager.
  • Se a hierarquia de visualização não estiver mais disponível porque o usuário concluiu uma etapa no fluxo de trabalho (por exemplo, o usuário fez login usando um formulário de login), chame commit() no objeto AutofillManager.
  • Se a hierarquia de visualização não for mais válida porque o usuário cancelou uma etapa no fluxo de trabalho (por exemplo, se o usuário clicou em um botão que limpa um formulário de login), chame cancel() no objeto AutofillManager.

Usar callbacks em eventos de preenchimento automático

Se seu app fornecer visualizações próprias de preenchimento automático, você precisará de um mecanismo que instrua o app a ativar ou desativar as visualizações em resposta a alterações na affordance de preenchimento automático da IU. A estrutura de preenchimento automático fornece esse mecanismo na forma de AutofillCallback.

Essa classe fornece o método onAutofillEvent(View, int), que o app chama depois de uma alteração no estado de preenchimento automático associado a uma visualização. Existe também uma versão sobrecarregada desse método, que inclui um parâmetro childId que seu app pode usar com visualizações virtuais. Os estados disponíveis são definidos como constantes no callback.

Você pode registrar um callback usando o método registerCallback() da classe AutofillManager. O exemplo de código a seguir mostra como declarar um callback para eventos de preenchimento automático:

Kotlin

    val afm = context.getSystemService(AutofillManager::class.java)

    afm?.registerCallback(object : AutofillManager.AutofillCallback() {
        // For virtual structures, override
        // onAutofillEvent(View view, int childId, int event) instead.
        override fun onAutofillEvent(view: View, event: Int) {
            super.onAutofillEvent(view, event)
            when (event) {
                EVENT_INPUT_HIDDEN -> {
                    // The autofill affordance associated with the view was hidden.
                }
                EVENT_INPUT_SHOWN -> {
                    // The autofill affordance associated with the view was shown.
                }
                EVENT_INPUT_UNAVAILABLE -> {
                    // Autofill isn't available.
                }
            }

        }
    })
    

Java

    AutofillManager afm = getContext().getSystemService(AutofillManager.class);

    afm.registerCallback(new AutofillManager.AutofillCallback() {
        // For virtual structures, override
        // onAutofillEvent(View view, int childId, int event) instead.
        @Override
        public void onAutofillEvent(@NonNull View view, int event) {
            super.onAutofillEvent(view, event);
            switch (event) {
                case EVENT_INPUT_HIDDEN:
                    // The autofill affordance associated with the view was hidden.
                    break;
                case EVENT_INPUT_SHOWN:
                    // The autofill affordance associated with the view was shown.
                    break;
                case EVENT_INPUT_UNAVAILABLE:
                    // Autofill isn't available.
                    break;
            }
        }
    });
    

Quando for o momento de remover o callback, use o método unregisterCallback().

Personalizar o drawable destacado com preenchimento automático

Quando uma visualização é preenchida automaticamente, a plataforma renderiza um Drawable sobre a visualização para indicar que o conteúdo da visualização foi preenchido automaticamente. Por padrão, esse desenho é um retângulo sólido com uma cor translúcida, ligeiramente mais escura do que a cor do tema usada para desenhar o plano de fundo. O drawable não precisa ser alterado, mas pode ser personalizado substituindo o item android:autofilledHighlight do tema usado pelo app ou atividade, como mostrado neste exemplo:

res/values/styles.xml

<resources>
        <style name="MyAutofilledHighlight" parent="...">
            <item name="android:autofilledHighlight">@drawable/my_drawable</item>
        </style>
    </resources>
    

res/drawable/my_drawable.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="#4DFF0000" />
    </shape>
    

AndroidManifest.xml

<application ...
        android:theme="@style/MyAutofilledHighlight">
    <!-- or -->
    <activity ...
        android:theme="@style/MyAutofilledHighlight">
    

Autenticar para o preenchimento automático

Um serviço de preenchimento automático pode exigir que o usuário faça a autenticação antes que o serviço possa preencher campos no seu app. Nesse caso, o sistema Android inicia a atividade de autenticação do serviço como parte da pilha da atividade.

Você não precisa atualizar seu app para oferecer compatibilidade com a autenticação porque a autenticação ocorre no serviço. No entanto, você precisa garantir que a estrutura de visualização da atividade seja preservada quando a atividade for reiniciada (por exemplo, criando a estrutura de visualização em onCreate(), não em onStart() ou onResume()).

Você pode verificar como seu app se comporta quando um serviço de preenchimento automático requer autenticação usando HeuristicsService da amostra AutofillFramework e configurando-o para exigir autenticação de resposta de preenchimento. Você também pode usar a amostra BadViewStructureCreationSignInActivity para emular esse problema.

Atribuir IDs de preenchimento automático a visualizações recicladas

Os contêineres que reciclam visualizações, como a classe RecyclerView, são muito úteis para apps que precisam exibir listas de rolagem de elementos com base em grandes conjuntos de dados. À medida que o contêiner rola, o sistema reutiliza as visualizações no layout, mas elas contêm novo conteúdo. Se o conteúdo inicial da visualização estiver preenchido, o serviço de preenchimento automático mantém o significado lógico das visualizações usando os IDs de preenchimento automático. Ocorre um problema quando, enquanto o sistema reutiliza as visualizações no layout, os IDs lógicos das visualizações permanecem os mesmos, fazendo com que dados errados de preenchimento automático do usuário sejam associados a um ID de preenchimento automático.

Para resolver esse problema em dispositivos com o Android 9 ou mais recente, é possível gerenciar explicitamente o ID de preenchimento automático de visualizações usadas por RecyclerView usando esses novos métodos:

  • O método getNextAutofillId() recebe um novo ID de preenchimento automático exclusivo para a atividade.
  • O método setAutofillId() define o ID de preenchimento automático lógico e exclusivo dessa visualização na atividade.

Resolver problemas conhecidos

Esta seção apresenta soluções alternativas para problemas conhecidos na estrutura de preenchimento automático.

As caixas de diálogo redimensionadas não são consideradas para o preenchimento automático

No Android 8.1 (API de nível 27) e versões anteriores, se uma visualização em uma caixa de diálogo for redimensionada depois de ser exibida, a visualização não será considerada para preenchimento automático. Essas visualizações não são incluídas no objeto AssistStructure que o sistema Android envia ao serviço de preenchimento automático. Como resultado, o serviço não pode preencher as visualizações.

Para contornar esse problema, substitua a propriedade token dos parâmetros da caixa de diálogo pela propriedade token da atividade que cria a caixa de diálogo. Depois de confirmar que o preenchimento automático está ativado, salve os parâmetros no método onWindowAttributesChanged() da classe que herda de Dialog. Em seguida, substitua a propriedade token dos parâmetros salvos pela propriedade token da atividade principal no método onAttachedToWindow().

O snippet de código a seguir mostra uma classe que implementa a solução alternativa:

Kotlin

    class MyDialog(context: Context) : Dialog(context) {

        // Used to store the dialog window parameters.
        private var token: IBinder? = null

        private val isDialogResizedWorkaroundRequired: Boolean
            get() {
                if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
                    return false
                }
                val autofillManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    context.getSystemService(AutofillManager::class.java)
                } else {
                    null
                }
                return autofillManager?.isEnabled ?: false
            }

        override fun onWindowAttributesChanged(params: WindowManager.LayoutParams) {
            if (params.token == null && token != null) {
                params.token = token
            }

            super.onWindowAttributesChanged(params)
        }

        override fun onAttachedToWindow() {
            if (isDialogResizedWorkaroundRequired) {
                token = ownerActivity!!.window.attributes.token
            }

            super.onAttachedToWindow()
        }

    }
    

Java

    public class MyDialog extends Dialog {

        public MyDialog(Context context) {
            super(context);
        }

        // Used to store the dialog window parameters.
        private IBinder token;

        @Override
        public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
            if (params.token == null && token != null) {
                params.token = token;
            }

            super.onWindowAttributesChanged(params);
        }

        @Override
        public void onAttachedToWindow() {
            if (isDialogResizedWorkaroundRequired()) {
                token = getOwnerActivity().getWindow().getAttributes().token;
            }

            super.onAttachedToWindow();
        }

        private boolean isDialogResizedWorkaroundRequired() {
            if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O
                    || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
                return false;
            }
            AutofillManager autofillManager =
                    null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                autofillManager = getContext().getSystemService(AutofillManager.class);
            }
            return autofillManager != null && autofillManager.isEnabled();
        }

    }
    

Para evitar operações desnecessárias, o snippet de código a seguir mostra como verificar se o preenchimento automático é compatível com o dispositivo, se está ativado para o usuário atual e se essa alternativa é necessária:

Kotlin

    // AutofillExtensions.kt

    fun Context.isDialogResizedWorkaroundRequired(): Boolean {
        // After the issue is resolved on Android, you should check if the
        // workaround is still required for the current device.
        return isAutofillAvailable()
    }

    fun Context.isAutofillAvailable(): Boolean {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // The autofill framework is only available on Android 8.0
            // or higher.
            return false
        }

        val afm = getSystemService(AutofillManager::class.java)
        // Return true if autofill is supported by the device and enabled
        // for the current user.
        return afm != null && afm.isEnabled
    }
    

Java

    public class AutofillHelper {

        public static boolean isDialogResizedWorkaroundRequired(Context context) {
            // After the issue is resolved on Android, you should check if the
            // workaround is still required for the current device.
            return isAutofillAvailable(context);
        }

        public static boolean isAutofillAvailable(Context context) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
                // The autofill framework is only available on Android 8.0
                // or higher.
                return false;
            }

            AutofillManager afm = context.getSystemService(AutofillManager.class);
            // Return true if autofill is supported by the device and enabled
            // for the current user.
            return afm != null && afm.isEnabled();
        }
    }
    

Testar seu app com o preenchimento automático

A maioria dos apps funciona com serviços de preenchimento automático sem nenhuma alteração. No entanto, você pode otimizar seu app para garantir que ele funcione da melhor forma possível com os serviços de preenchimento automático. Depois de otimizar seu app, é necessário testá-lo para garantir que ele funcione como pretendido com os serviços de preenchimento automático.

Use um emulador ou um dispositivo físico com o Android 8.0 (API de nível 26) ou versão mais recente para testar seu app. Para ver mais informações sobre como criar um emulador, consulte Criar e gerenciar dispositivos virtuais.

Instalar um serviço de preenchimento automático

Antes de testar seu app com o preenchimento automático, você precisa instalar outro app que forneça serviços de preenchimento automático. Você pode usar um app de terceiros para esse fim, mas é mais fácil usar um serviço de preenchimento automático de exemplo para não precisar se inscrever em serviços de terceiros.

Você pode usar a amostra da estrutura de preenchimento automático do Android para testar seu app com serviços de preenchimento automático. O app de exemplo fornece um serviço de preenchimento automático e classes clientes Activity que podem ser usados para testar o fluxo de trabalho antes de usá-lo com seu app. Esta página faz referência ao app de exemplo android-AutofillFramework.

Depois de instalar o app, ative o serviço de preenchimento automático nas configurações do sistema. É possível ativar o serviço navegando para Config. > Sistema > Idioma e entrada > Avançado > Assistência de entradas > Serviço de preenchimento automático.

Analisar requisitos de dados

Para testar seu app com o serviço de preenchimento automático, o serviço precisa ter dados que possam ser usados para preencher o app. Ele também precisa entender os tipos de dados esperados nas visualizações do seu app. Por exemplo, se seu aplicativo tiver uma visualização que espera um nome de usuário, o serviço deverá ter um conjunto de dados que contenha um nome de usuário e algum mecanismo para saber que a visualização espera tais dados.

Você precisa permitir que o serviço saiba que tipo de dados é esperado nas suas visualizações, definindo o atributo android:autofillHints. Alguns serviços usam heurística sofisticada para determinar o tipo de dados, mas outros, como o app de exemplo, dependem do desenvolvedor para fornecer essas informações. Seu app funciona melhor com os serviços de preenchimento automático se você definir o android:autofillHints nas visualizações relevantes para o preenchimento automático.

Executar seu teste

Depois de analisar os requisitos de dados, você pode executar o teste, o que inclui salvar os dados de teste no serviço de preenchimento automático e acionar o preenchimento automático no app.

Salvar dados no serviço

As etapas a seguir mostram como salvar dados no serviço de preenchimento automático ativo:

  1. Abra um app que contenha uma visualização que precise do tipo de dados que você quer usar durante o teste. O app de exemplo android-AutofillFramework fornece à IU visualizações que esperam vários tipos de dados, como números de cartão de crédito e nomes de usuários.
  2. Toque na visualização que contém o tipo de dados que você precisa.
  3. Digite um valor na visualização.
  4. Toque no botão de confirmação, como Fazer login ou Enviar.

    Geralmente, você precisa enviar o formulário antes que o serviço tente salvar os dados.

  5. O sistema exibe uma caixa de diálogo solicitando sua permissão para salvar os dados. A caixa de diálogo mostra o nome do serviço que está ativo no momento.

    Verifique se esse é o serviço que você quer usar no seu teste e toque em Salvar.

Se o Android não exibir a caixa de diálogo de permissão ou se o serviço não for o que você quer usar no teste, verifique se o serviço está ativo nas configurações do sistema.

Acionar o preenchimento automático no seu app

As etapas a seguir mostram como acionar o preenchimento automático no seu app:

  1. Abra seu app e acesse a atividade que tem as visualizações que você quer testar.
  2. Toque na visualização que precisa ser preenchida.
  3. O sistema deve exibir a IU de preenchimento automático, que contém os conjuntos de dados que podem preencher a visualização, como mostrado na Figura 1.
  4. Toque no conjunto que contém os dados que você quer usar. A visualização precisa exibir os dados armazenados anteriormente no serviço.
IU de preenchimento automático exibindo
Figura 1. IU de preenchimento automático exibindo os conjuntos de dados disponíveis.

Se o Android não exibir a interface de preenchimento automático, tente as seguintes opções de solução de problemas:

  • Verifique se as visualizações no seu app usam o valor correto no atributo android:autofillHints. Para ver uma lista de valores possíveis para o atributo, consulte as constantes prefixadas com AUTOFILL_HINT na classe View.
  • Verifique se o atributo android:importantForAutofill está definido como um valor diferente de no na visualização que precisa ser preenchida, ou configure com um valor diferente de noExcludeDescendants na visualização ou em um dos pais dela.