Participe do evento ⁠#Android11: apresentação de lançamento da versão Beta no dia 3 de junho.

Referência do licenciamento

Classes e interfaces da LVL

A Tabela 1 lista todos os arquivos de origem na biblioteca License Verification (LVL, link 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 biblioteca 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 aplicativo 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ê estiver 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ê quiser restringir o uso de um aplicativo para um dispositivo específico. Chamado do LicenseValidator. Não é recomendado implementar o DeviceLimiter na maioria dos aplicativos 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 aplicativos licenciados.
NullDeviceLimiter Implementação padrão do DeviceLimiter. É um ambiente autônomo (permite o acesso para 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 aplicativo 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 aplicativo gerencie todos esses códigos de resposta. Por padrão, a classe LicenseValidator na LVL oferece todo o gerenciamento 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 aplicativo 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 aplicativo. Sim VT, GT, GR Permita o acesso de acordo com as restrições de Policy.
LICENSED_OLD_KEY O aplicativo 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 aplicativo é inválido ou está comprometido. O aplicativo 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 aplicativo não está licenciado para o usuário. Não Não permita o acesso.
ERROR_CONTACTING_SERVER Erro local: o aplicativo 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 aplicativo 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 aplicativo 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 aplicativo 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 aplicativo 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 aplicativo (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 aplicativo não foi publicado pelo Google Play ou que há um erro de desenvolvimento na implementação do licenciamento.

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

Observação: antes, era possível testar um aplicativo 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 aplicativo 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 aplicativo, período de carência da nova tentativa, contagem máxima permitida de novas tentativas e outras configurações. Se o aplicativo 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) expira e precisa 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 Policy pode permitir acesso ao aplicativo, 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 aplicativo.

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 aplicativo foi enviada e publicada.

O servidor retorna este extra somente 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 aplicativo.

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 aplicativos transferidos por download. O período expressa o intervalo de tempo em que o status de licença de um aplicativo será considerado inalterável e armazenável em cache por uma Policy de licenciamento presente no aplicativo. 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 à resposta como um extra na chave VT. Uma Policy pode extrair a chave-valor VT e usá-la para permitir condicionalmente o acesso ao aplicativo 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 com o servidor. O objetivo não é sugerir que um aplicativo está licenciado para uso. Ou seja, a expiração do período de validade de uma licença não significa que o aplicativo não está mais licenciado para uso. Ela indica apenas que a Policy precisa verificar novamente o status de licenciamento com o 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 aplicativo a aplicar adequadamente o licenciamento durante o período de reembolso oferecido pelo Google Play a aplicativos pagos. Ele define o período de validade com base no status e no momento de compra do aplicativo. O servidor define um período de validade da seguinte maneira:

  • Para um aplicativo 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 aplicativo pode armazenar o resultado da verificação de licença inicial em cache e não precisa verificar novamente a licença até que o período de validade tenha expirado.
  • Quando um aplicativo 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 aplicativo 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 é necessário verificar novamente o status da licença com o servidor antes de permitir que o usuário acesse o aplicativo.

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 aplicativo chegue ao servidor de licenciamento ou que a resposta do servidor chegue ao aplicativo cliente do Google Play. Por exemplo, o usuário pode abrir um aplicativo quando não houver rede celular ou conexão de dados disponível, como no avião, ou quando a conexão de rede estiver instável ou o sinal celular estiver fraco.

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

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

O servidor do Google Play ajuda um aplicativo 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 aplicativo pode extrair os extras GT e GR e usá-los para permitir condicionalmente o acesso ao aplicativo, da seguinte maneira:

  • Para uma verificação de licença que resulta 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 aplicativo, 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;
    }