Otimizar seu aplicativo para o preenchimento automático

Nos apps que usam visualizações padrão, a Estrutura de preenchimento automático funciona sem precisar de configuração especial. Além disso, é possível otimizar a forma como seu app funciona com essa Estrutura.

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 (nível 26 da API) e versões mais recentes ofereça um preenchimento automático, recomendamos que você use um serviço de teste no seu app, como o exemplo Estrutura de preenchimento automático do Android (link em inglês). Ao usar um emulador, configure o preenchimento automático de forma explícita, porque é possível que ele não tenha um serviço padrão.

Depois de instalar o preenchimento automático de teste do app de exemplo, ative-o em Configurações > Sistema > Idioma e entrada > Avançado > Assistência para entrada de texto > Preenchimento automático.

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

Dar dicas para o preenchimento automático

O preenchimento automático usa heurísticas para determinar o tipo de cada visualização. No entanto, se o app depende dessas heurísticas, o comportamento de preenchimento automático pode mudar de forma inesperada quando ele é atualizado. Para garantir que o serviço identifique corretamente os formatos do app, forneça dicas de preenchimento automático.

Você pode definir as dicas de preenchimento automático usando o atributo android:autofillHints. O exemplo a seguir define a dica "password" em um 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(), como 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);

Incluir constantes de dica predefinidas

A Estrutura de preenchimento automático não valida as dicas. Elas são transmitidas sem modificação ou validação para o preenchimento automático. Embora seja possível usar qualquer valor, a classe HintConstants do AndroidX e a View contêm listas de constantes de dica com suporte oficial.

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

Credenciais da conta

Em um formulário de login, você pode incluir dicas de credenciais da conta, como AUTOFILL_HINT_USERNAME e AUTOFILL_HINT_PASSWORD.

Para criar uma nova conta ou quando houver mudança no nome de usuário e na senha, use 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

Para campos de endereço físico em formulários, use dicas como as seguintes:

Nomes de pessoas

Ao solicitar nomes de pessoas, use dicas como as seguintes:

.

Números de telefone

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

Senha única (OTP)

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

Quando tiver várias visualizações e cada uma estiver associada a um único dígito da OTP, utilize o método generateSmsOtpHintForCharacterPosition() para gerar dicas por caractere.

Marcar campos como importantes para o preenchimento automático

Você pode incluir os campos do app em uma estrutura de visualização para habilitar o preenchimento automático. Por padrão, as visualizações usam o modo IMPORTANT_FOR_AUTOFILL_AUTO, que permite que o Android utilize as heurísticas dele para determinar se uma visualização é importante para o preenchimento automático.

Contudo, há casos em que uma visualização, uma estrutura de visualização ou uma atividade inteira não é importante para o preenchimento automático, como:

  • Um campo CAPTCHA em uma atividade de login
  • Uma visualização em que o usuário cria conteúdo, como um editor de texto ou de planilhas
  • As visualizações em algumas atividades em jogos, como aquelas que mostram a jogabilidade

Você pode definir a importância de uma visualização para o preenchimento automático com o atributo android:importantForAutofill:

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

O valor de importantForAutofill pode ser definido como uma das seguintes opções:

auto
Permite que o sistema Android use as heurísticas 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);

Para declarar que os exemplos anteriores de casos de uso não são importantes para o preenchimento automático, faça o seguinte:

  • Um campo CAPTCHA em uma atividade de login: use android:importantForAutofill="no" ou IMPORTANT_FOR_AUTOFILL_NO para marcar essa visualização como não importante.
  • Uma visualização em que o usuário cria conteúdo: use android:importantForAutofill="noExcludeDescendants" ou IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS para marcar toda a estrutura de visualização como não importante.
  • Visualizações em algumas atividades em jogos: use android:importantForAutofill="noExcludeDescendants" ou IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS para marcar toda a estrutura de visualização como não importante.

Associar os dados de sites e 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 nas duas plataformas, fazer login no app da Web disponibiliza as credenciais para preenchimento automático quando a conta for se conectar no app Android correspondente.

Para associar o app Android ao seu site, hospede um Digital Asset Link 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 ter 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

Os usuários podem ativar ou desativar o preenchimento automático e mudar esse serviço navegando até Configurações > Sistema > Idioma e entrada > Avançado > Assistência para entrada de texto > Preenchimento automático. O app não pode substituir as configurações de preenchimento automático do usuário, mas é possível implementar outras funções semelhantes nele ou em visualizações específicas caso o serviço esteja disponível.

Por exemplo, TextView mostra uma entrada de preenchimento automático no menu flutuante quando esse serviço está ativado para o usuário. Para conferir se o preenchimento automático está ativado, chame o método isEnabled() do objeto AutofillManager.

Para garantir que a experiência de inscrição e login do app seja a melhor possível para usuários que não ativaram o preenchimento automático, implemente o login com um toque.

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

Às vezes, pode ser necessário forçar uma solicitação de preenchimento automático em resposta a uma ação do usuário. Por exemplo, a classe TextView oferece um item de menu com preenchimento automático quando o usuário toca na visualização e 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 de preenchimento automático atual. Isso poderá ser útil se houver um botão que limpe os campos em uma página de login.

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

Os seletores podem ser úteis em algumas situações de preenchimento automático, porque fornecem uma interface para que os usuários mudem 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 mudem a data de validade do cartão. No entanto, você vai precisar usar outra visualização, como EditText, para mostrar os dados quando o seletor não estiver visível.

Um objeto EditText espera dados de preenchimento automático do tipo AUTOFILL_TYPE_TEXT de forma nativa. Caso esteja usando outro tipo de dados, crie uma visualização personalizada que seja herdada de EditText e que implementa os métodos necessários para processar o tipo correspondente. Por exemplo, em 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, o serviço pode criar uma representação adequada dos dados que aparecem na visualização. Para mais informações, consulte 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, é possível concluir o contexto explicitamente chamando AutofillManager.commit().

Suporte a 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 interface renderizada por OpenGL. Essas visualizações precisam usar a API para especificar a estrutura das informações usadas no app e se tornarem compatíveis com a Estrutura de preenchimento automático.

Se o app usa visualizações personalizadas, considere estas possibilidades:

  • A visualização personalizada fornece uma estrutura de visualização padrão ou 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

A visualização personalizada pode definir os metadados necessários para que o preenchimento automático funcione. Confira se ela gerencia os metadados de forma adequada para se compatível com a Estrutura de preenchimento automático. A visualização personalizada precisa executar estas ações:

  • Processar 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 chama autofill() na visualização e envia o valor que ela precisa usar. Implemente autofill() para especificar como a visualização personalizada processa o valor do preenchimento automático.

A visualização precisa especificar um tipo e um valor de preenchimento automático, substituindo os métodos getAutofillType() e getAutofillValue(), respectivamente.

Por fim, o preenchimento automático não pode preencher a visualização caso o usuário não possa fornecer um valor para ela no estado atual (por exemplo, se 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 sensíveis.

A visualização personalizada é editável.

Se a visualização for editável, informe a Estrutura de preenchimento automático sobre as mudanças chamando notifyValueChanged() no objeto AutofillManager.

A visualização personalizada contém dados sensíveis

Se a visualização tiver informações de identificação pessoal (PII), como endereços de e-mail, números de cartão de crédito e senhas, ela precisará ser marcada como sensível.

No geral, visualizações que têm conteúdo proveniente de recursos estáticos não contêm dados sensíveis, mas as que têm conteúdo definido de modo dinâmico podem incluir esses tipos de dados. Por exemplo, um marcador com a mensagem digite seu nome de usuário não contém dados sensíveis, mas um com a mensagem Olá, João, sim.

Por padrão, a Estrutura de preenchimento automático considera que todos os dados são sensíveis. Se preferir, você pode indicar quais não são.

Para indicar que uma visualização contém dados sensíveis, 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 não sensíveis:

Kotlin

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

    structure.setDataIsSensitive(false)
}

Java

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

    structure.setDataIsSensitive(false);
}

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 dela. Mais especificamente, as visualizações com preenchimento automático do tipo AUTOFILL_TYPE_LIST precisam usar esse método porque o serviço pode realizar um trabalho melhor se conhecer as opções disponíveis para preencher a visualização.

O caso das visualizações que usam um adaptador, como um Spinner, é parecido com esse. Por exemplo, um controle giratório que apresenta anos gerados de forma dinâmica, a partir do ano atual, para preenchimento de campos de validade do cartão de crédito pode implementar o método getAutofillOptions() da interface Adapter para fornecer uma lista de anos.

As visualizações que usam um ArrayAdapter também podem fornecer listas de valores. O ArrayAdapter define automaticamente as opções de preenchimento automático para recursos estáticos. Caso os valores sejam fornecidos de forma dinâmica, substitua 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 interface do seu app. A estrutura de visualização não está disponível nas seguintes situações:

  • O app usa um mecanismo de renderização de baixo nível, como OpenGL (link em inglês), para renderizar a interface.
  • O app usa uma instância de Canvas para desenhar a interface.

Nesses casos, é possível 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 um filho chamando newChild().
  3. Defina o ID de preenchimento automático do filho chamando setAutofillId().
  4. Defina as propriedades relevantes, como o valor e o tipo de preenchimento automático.
  5. Se os dados no filho virtual forem sensíveis, transmita true para setDataIsSensitive(). Caso contrário, transmita false.

O snippet de código a seguir mostra como criar um novo filho 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, such as when 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 when
    // 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, such as when the child is
    // a spinner.
    CharSequence childAutofillOptions[] = { "option1", "option2" };
    child.setAutofillOptions(childAutofillOptions);

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

Quando os elementos em uma estrutura virtual mudam, é necessário notificar a Estrutura de preenchimento automático. Para isso, faça o seguinte:

  • Se o foco dentro dos filhos mudou, chame notifyViewEntered() e notifyViewExited() no objeto AutofillManager.
  • Se o valor de um filho 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, como fazer login usando um formulário de login, chame commit() no objeto AutofillManager.
  • Se a hierarquia de visualização não for válida porque o usuário cancelou uma etapa no fluxo de trabalho, como tocar 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 o seu app fornecer visualizações próprias de preenchimento automático, você vai precisar de um mecanismo que instrua o app a ativar ou desativar as visualizações em resposta a mudanças na affordance de preenchimento automático da interface. 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 mudança 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 pode ser usado pelo app 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 drawable é 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 modificado, mas pode ser personalizado substituindo o item android:autofilledHighlight do tema usado pelo app ou pela 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 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.

Não é necessário atualizar o app para oferecer suporte à autenticação, porque ela é realizada dentro do serviço. No entanto, você precisa garantir que a estrutura de visualização da atividade seja preservada quando ela for reiniciada, por exemplo, criando essa estrutura em onCreate(), não em onStart() ou onResume().

É possível verificar como o app se comporta quando um serviço de preenchimento automático exige autenticação. Para isso, use o HeuristicsService (link em inglês) do exemplo AutofillFramework e configure-o para exigir autenticação de resposta de preenchimento. Você também pode usar o exemplo BadViewStructureCreationSignInActivity (link em inglês) 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 mostrar 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 mostram conteúdo novo.

Se o conteúdo inicial da visualização reciclada for preenchido, o serviço de preenchimento automático vai manter 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 (nível 28 da API) ou versões mais recentes, gerencie explicitamente o ID de preenchimento automático de visualizações usadas por RecyclerView implementando estes 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.

O preenchimento automático faz com que os aplicativos falhem no Android 8.0, 8.1

No Android 8.0 (nível 26 da API) e 8.1 (nível 27 da API), o preenchimento automático pode fazer com que seu app falhe em determinados cenários. Para contornar possíveis problemas, marque todas as visualizações que não são preenchidas automaticamente com importantForAutofill=no. Você também pode marcar toda a atividade com importantForAutofill=noExcludeDescendants.

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

No Android 8.1 (nível 27 da API) e versões anteriores, se uma visualização em uma caixa de diálogo for redimensionada depois de aparecer, a visualização não vai ser considerada para preenchimento automático. Essas visualizações não são incluídas no objeto AssistStructure que o sistema Android envia ao 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 herdada 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 essa 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 há suporte para o preenchimento automático no dispositivo, se ele está ativado para o usuário atual e se essa solução alternativa é necessária:

Kotlin

// AutofillExtensions.kt

fun Context.isDialogResizedWorkaroundRequired(): Boolean {
    // After the issue is resolved on Android, check whether 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 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, check whether 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 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 o app com o preenchimento automático

Depois de otimizar seu app para funcionar com os serviços de preenchimento automático, teste se ele está funcionando da maneira esperada.

Use um emulador ou um dispositivo físico com o Android 8.0 (nível 26 da API) ou versões mais recentes para testar o app. Para 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 esse tipo de serviço. Você pode usar um app de terceiros para esse fim, mas é mais fácil usar o preenchimento automático de exemplo para não precisar se inscrever em serviços de terceiros.

Você pode usar o exemplo da Estrutura de preenchimento automático do Android em Java (link em inglês) para testar o preenchimento automático no app. O app de exemplo inclui o preenchimento automático e classes Activity cliente que podem ser usados para testar o fluxo de trabalho antes da implementação no seu app. Esta página faz referência ao app de exemplo android-AutofillFramework.

Depois de instalar o app, ative o preenchimento automático nas configurações do sistema do emulador. Para isso, acesse Configurações > Sistema > Idioma e entrada > Avançado > Assistência para entrada de texto > Preenchimento automático.

Analisar requisitos de dados

Para testar o preenchimento automático no app, é necessário ter acesso aos dados que podem ser usados para preencher os campos correspondentes. Além disso, esse serviço precisa entender os tipos de dados esperados em cada visualização do app. Por exemplo, se houver uma visualização que requer um nome de usuário, o preenchimento automático vai precisar de um conjunto de dados que contenha um nome de usuário e algum mecanismo para determinar que a visualização espera esse tipo de dados.

Para informar ao preenchimento automático quais tipos de dados são esperados nas visualizações, configure o atributo android:autofillHints. Alguns serviços usam heurísticas sofisticadas para determinar o tipo necessário, enquanto outros, como o app de exemplo, dependem do desenvolvedor para receber essas informações. O preenchimento automático vai funcionar melhor no app se você definir o atributo android:autofillHints nas visualizações que utilizam esse serviço.

Executar o teste

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

Salvar dados no serviço

Para salvar os dados no preenchimento automático ativo, faça o seguinte:

  1. Abra um app que contenha uma visualização que precisa do tipo de dados que você quer usar durante o teste. O app de exemplo android-AutofillFramework fornece à interface 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. Insira um valor na visualização.
  4. Toque no botão de confirmação, como Fazer login ou Enviar. No geral, é necessário enviar o formulário para que o serviço salve os dados.
  5. Verifique a solicitação de permissão na caixa de diálogo do sistema. Essa caixa mostra o nome do serviço que está ativo no momento e pergunta se é ele que você quer usar no teste. Se quiser usar esse serviço, toque em Salvar.

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

Acionar o preenchimento automático no app

Para acionar o preenchimento automático no seu app, faça o seguinte:

  1. Abra o 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 vai mostrar a interface de preenchimento automático, que contém os conjuntos de dados que podem preencher a visualização, conforme mostrado na Figura 1.
  4. Toque no conjunto que contém os dados que você quer usar. A visualização mostra os dados armazenados anteriormente pelo serviço.
Interface de preenchimento automático mostrando "dataset-2" como um conjunto de dados disponível.
Figura 1. IU de preenchimento automático exibindo os conjuntos de dados disponíveis.

Se o Android não mostrar a UI de preenchimento automático, tente seguir estas opções de solução de problemas:

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