O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Referência do licenciamento

Classes e interfaces da LVL

A Tabela 1 lista todos os arquivos de origem na Verificação de Licença Library (LVL, na sigla em inglês) disponível pelo SDK do Android. Todos os arquivos fazem parte do pacote com.android.vending.licensing.

Tabela 1. Resumo das classes e interfaces da LVL.

Categoria Nome Descrição
Verificação de licença e resultado LicenseChecker Classe (ou subclasse) instanciada para iniciar uma verificação de licença.
LicenseCheckerCallback Interface implementada para gerenciar o resultado da verificação de licença.
Política Policy Interface implementada para determinar a permissão de acesso ao app com base na resposta da licença.
ServerManagedPolicy Implementação padrão de Policy. Usa as configurações fornecidas pelo servidor de licenciamento para gerenciar o armazenamento local de novas tentativas, dados e validade da licença.
StrictPolicy Implementação alternativa de Policy. Aplica o licenciamento com base em uma resposta de licença direta exclusiva do servidor. Sem cache ou solicitação de nova tentativa.
Ofuscação de dados
(opcional)
Obfuscator Interface implementada quando você está usando uma Policy (como ServerManagedPolicy) que cria o cache dos dados de resposta de licença em um armazenamento persistente. Aplica um algoritmo de ofuscação para codificar e decodificar os dados que estão sendo gravados ou lidos.
AESObfuscator Implementação padrão do Obfuscator. Usa o algoritmo de codificação/decodificação AES para ofuscar/desofuscar os dados.
Limitação de dispositivos
(opcional)
DeviceLimiter Interface implementada quando você quer restringir o uso de um apppara um dispositivo específico. Chamado do LicenseValidator. Não é recomendado implementar o DeviceLimiter na maioria dos apps porque ele precisa de um servidor de back-end e, a menos que seja desenvolvido com cuidado, pode fazer com que o usuário perca acesso a apps licenciados.
NullDeviceLimiter Implementação padrão do DeviceLimiter. É um ambiente autônomo (permite o acesso a todos os dispositivos).
Núcleo da biblioteca, sem necessidade de integração ResponseData Classe que contém os campos de uma resposta de licença.
LicenseValidator Classe que descriptografa e verifica uma resposta recebida do servidor de licenciamento.
ValidationException Classe que indica erros que ocorrem ao validar a integridade de dados gerenciados por um Obfuscator.
PreferenceObfuscator Classe de utilitário que grava/lê dados ofuscados no armazenamento de SharedPreferences do sistema.
ILicensingService Interface de IPC unidirecional em que uma solicitação de verificação de licença é transmitida ao cliente do Google Play.
ILicenseResultListener Implementação de callback de IPC unidirecional em que o app recebe uma resposta assíncrona do servidor de licenciamento.

Códigos de resposta do servidor

A Tabela 2 lista todos os códigos de resposta de licença aceitos pelo servidor de licenciamento. O esperado é que um app consiga processar todos esses códigos de resposta. Por padrão, a classe LicenseValidator na LVL oferece todo o processamento necessário desses códigos para você.

Tabela 2. Resumo dos códigos de resposta retornados pelo servidor do Google Play em uma resposta de licença.

Código de resposta Descrição Assinado? Extras Comentários
LICENSED O app está licenciado para o usuário. O usuário comprou ou está autorizado a fazer o download e instalar a versão Alfa ou Beta do app. Sim VT, GT, GR Permita o acesso de acordo com as restrições de Policy.
LICENSED_OLD_KEY O app está licenciado para o usuário, mas há uma versão atualizada disponível que está assinada com uma chave diferente. Sim VT, GT, GR, UT Opcionalmente, conceda o acesso de acordo com as restrições de Policy.

Pode indicar que o par de chaves usado pela versão instalada do app é inválido ou está comprometido. O app pode permitir o acesso se necessário ou informar ao usuário de um upgrade disponível e limitar o uso até que o upgrade seja feito.

NOT_LICENSED O app não está licenciado para o usuário. Não Não permita o acesso.
ERROR_CONTACTING_SERVER Erro local: o app Google Play não conseguiu acessar o servidor de licenciamento, possivelmente devido a problemas de disponibilidade da rede. Não Tente fazer a verificação da licença novamente de acordo com os limites de novas tentativas da Policy.
ERROR_SERVER_FAILURE Erro de servidor: não foi possível carregar o par de chaves do app para licenciamento no servidor. Não Tente fazer a verificação da licença novamente de acordo com os limites de novas tentativas da Policy.
ERROR_INVALID_PACKAGE_NAME Erro local: o app solicitou uma verificação de licença para um pacote que não está instalado no dispositivo. Não Não tente fazer a verificação da licença novamente.

Geralmente causado por um erro de desenvolvimento.

ERROR_NON_MATCHING_UID Erro local: o app solicitou uma verificação de licença para um pacote cujo UID (par de IDs do usuário e pacote) não corresponde ao pacote do app solicitante. Não Não tente fazer a verificação da licença novamente.

Geralmente causado por um erro de desenvolvimento.

ERROR_NOT_MARKET_MANAGED Erro de servidor: o app (nome do pacote) não foi reconhecido pelo Google Play. Não Não tente fazer a verificação da licença novamente.

Pode indicar que o app não foi publicado pelo Google Play ou que há um erro de desenvolvimento na implementação do licenciamento.

Observação: como documentado em Como configurar o ambiente de testes, o código de resposta pode ser modificado manualmente pelo desenvolvedor do app e por usuários de teste registrados pelo Google Play Console.

Observação: antes, era possível testar um app fazendo upload de uma versão de "rascunho" não publicada. Essa funcionalidade não está mais disponível. Agora, você precisa publicá-lo nos canais de distribuição Alfa ou Beta. Para saber mais, consulte Aplicativos de rascunho não são mais compatíveis.

Extras de resposta do servidor

Para ajudar seu app a gerenciar o acesso durante o período de reembolso e fornecer outras informações, o servidor de licenciamento inclui várias informações nas respostas da licença. Especificamente, o serviço fornece valores recomendados para o período de validade da licença do app, período de carência da nova tentativa, contagem máxima permitida de novas tentativas e outras configurações. Se o app usar arquivos de expansão do APK, a resposta também incluirá nomes, tamanhos e URLs de arquivos. O servidor anexará as configurações como pares de chave-valor no campo "extras" da resposta de licença.

Qualquer implementação de Policy pode extrair as configurações extras da resposta de licença e usá-las conforme necessário. A implementação padrão de Policy da LVL, ServerManagedPolicy, serve como uma implementação funcional e uma ilustração de como coletar, armazenar e usar as configurações.

Tabela 3. Resumo das configurações de gerenciamento de licenças fornecidas pelo servidor do Google Play em uma resposta de licença.

ExtraDescrição
VT Carimbo de data/hora de validade da licença. Especifica a data e a hora em que a resposta de licença atual (armazenada em cache) expirará e precisará ser verificada novamente no servidor de licenciamento. Consulte a seção abaixo sobre Período de validade da licença.
GT Carimbo de data/hora do período de carência. Especifica o fim do período em que uma política pode permitir acesso ao app, mesmo que o status da resposta seja RETRY.

O valor é gerenciado pelo servidor. No entanto, um valor típico seria de cinco dias ou mais. Consulte a seção abaixo sobre Período e contagem máxima de novas tentativas.

GR Contagem máxima de novas tentativas. Especifica quantas verificações de licença RETRY consecutivas a Policy permitirá antes de negar o acesso do usuário ao app.

O valor é gerenciado pelo servidor. No entanto, um valor típico seria de "10" ou mais. Consulte a seção abaixo sobre Período e contagem máxima de novas tentativas.

UT Carimbo de data/hora da atualização. Especifica o dia/hora em que a atualização mais recente do app foi enviada e publicada.

O servidor retorna este extra apenas para respostas LICENSED_OLD_KEYS. Isso é feito para permitir que Policy determine quanto tempo se passou desde que uma atualização foi publicada com novas chaves de licenciamento antes de negar o acesso do usuário ao app.

FILE_URL1 ou FILE_URL2 O URL de um arquivo de expansão: 1 é para o arquivo principal, 2 é o arquivo de patch. Use para fazer o download do arquivo por HTTP.
FILE_NAME1 ou FILE_NAME2 O nome do arquivo de expansão: 1 é para o arquivo principal, 2 é o arquivo de patch. Use esse nome ao salvar o arquivo no dispositivo.
FILE_SIZE1 ou FILE_SIZE2 O tamanho do arquivo em bytes: 1 é para o arquivo principal, 2 é o arquivo de patch. Use para ajudar no download e garantir que haja espaço suficiente disponível no local de armazenamento compartilhado do dispositivo antes do download.

Período de validade da licença

O servidor de licenciamento do Google Play define um período de validade para todos os apps transferidos por download. O período expressa o intervalo de tempo em que o status de licença de um app será considerado inalterável e armazenável em cache por uma Policy de licenciamento presente no app. O servidor de licenciamento inclui o período de validade na resposta para todas as verificações de licença, anexando um carimbo de fim de validade da resposta como um extra na chave VT. Uma Policy pode extrair a chave-valor VT e usá-la para permitir condicionalmente o acesso ao app sem verificar a licença novamente até que o período de validade expire.

A validade da licença enviará um sinal para uma Policy de licenciamento quando precisar verificar novamente o status de licenciamento no servidor. O objetivo não é sugerir que um app esteja licenciado para uso. Ou seja, a expiração do período de validade de uma licença não significa que o app não esteja mais licenciado para uso. Ela indica apenas que a Policy precisa verificar novamente o status de licenciamento no servidor. Desde que o período de validade da licença não tenha expirado, é aceitável que Policy armazene o status da licença inicial em cache localmente e retorne o status da licença em cache em vez de enviar uma nova verificação de licença ao servidor.

O servidor de licenciamento gerencia o período de validade como um meio de ajudar o app a aplicar adequadamente o licenciamento durante o período de reembolso oferecido pelo Google Play a apps pagos. Ele define o período de validade com base no status e no momento de compra do app. O servidor define um período de validade da seguinte maneira:

  • Para um app pago, o servidor define o período de validade da licença inicial para que a resposta da licença permaneça válida pelo período de reembolso. Uma Policy de licenciamento no app pode armazenar o resultado da verificação de licença inicial em cache e não será necessário verificar novamente a licença até que o período de validade tenha expirado.
  • Quando um app não é mais reembolsável, o servidor define um período de validade mais longo, normalmente marcado por um número de dias.
  • Para um app gratuito, o servidor define o período de validade como um valor muito alto (long.MAX_VALUE). Isso garante que, contanto que Policy tenha armazenado o carimbo de data/hora de validade localmente, não será necessário verificar novamente o status da licença no futuro.

A implementação de ServerManagedPolicy usa o carimbo de data/hora extraído (mValidityTimestamp) como condição principal para determinar se é preciso verificar novamente o status da licença com o servidor antes de permitir que o usuário acesse o app.

Período e contagem máxima de novas tentativas

Em alguns casos, as condições do sistema ou da rede podem impedir que uma verificação de licença de app chegue ao servidor de licenciamento ou que a resposta do servidor chegue ao app cliente do Google Play. Por exemplo, o usuário pode abrir um app quando não há rede celular ou conexão de dados disponível, como no avião, ou quando a conexão de rede está instável ou o sinal celular está fraco.

Quando problemas de rede impedem ou interrompem uma verificação de licença, o cliente do Google Play notifica o app retornando um código de resposta RETRY ao método processServerResponse() da Policy. No caso de problemas do sistema, como quando o app não consegue se vincular à implementação de ILicensingService do Google Play, a própria biblioteca de LicenseChecker chama o método processServerResonse() da política com um código de resposta RETRY.

Geralmente, o código de resposta RETRY é um sinal para o app de que ocorreu um erro que impediu a conclusão de uma verificação de licença.

O servidor do Google Play ajuda um app a gerenciar o licenciamento em condições de erro definindo um "período de carência" e uma contagem máxima recomendada de novas tentativas. O servidor inclui esses valores em todas as respostas de verificação de licença, anexando-os como extras nas chaves GT e GR.

A Policy do app pode extrair os extras GT e GR e usá-los para permitir condicionalmente o acesso ao app, da seguinte maneira:

  • Para uma verificação de licença que resulte em uma resposta RETRY, a Policy armazenará o código de resposta RETRY em cache e incrementará uma contagem de respostas RETRY.
  • A Policy permitirá que o usuário acesse o app, contanto que o período de carência de novas tentativas permaneça ativo ou que a contagem máxima não tenha sido atingida.

A ServerManagedPolicy usa os valores GT e GR fornecidos pelo servidor conforme descrito acima. O exemplo abaixo mostra o gerenciamento condicional das respostas de nova tentativa no método allow(). A contagem de respostas RETRY é mantida no método processServerResponse(), que não é mostrado.

Kotlin

fun allowAccess(): Boolean {
    val ts = System.currentTimeMillis()
    return when(lastResponse) {
        LICENSED -> {
            // Check if the LICENSED response occurred within the validity timeout.
            ts <= validityTimestamp  // Cached LICENSED response is still valid.
        }
        RETRY -> {
            ts < lastResponseTime + MILLIS_PER_MINUTE &&
                    // Only allow access if we are within the retry period
                    // or we haven't used up our max retries.
                    (ts <= retryUntil || retryCount <= maxRetries)
        }
        else -> false
    }
}

Java

public boolean allowAccess() {
    long ts = System.currentTimeMillis();
    if (lastResponse == LicenseResponse.LICENSED) {
        // Check if the LICENSED response occurred within the validity timeout.
        if (ts <= validityTimestamp) {
            // Cached LICENSED response is still valid.
            return true;
        }
    } else if (lastResponse == LicenseResponse.RETRY &&
                ts < lastResponseTime + MILLIS_PER_MINUTE) {
        // Only allow access if we are within the retry period
        // or we haven't used up our max retries.
        return (ts <= retryUntil || retryCount <= maxRetries);
    }
    return false;
}