Suporte para atualizações no app (Unity)

Este guia descreve como oferecer compatibilidade com as atualizações no app usando o Unity. Há guias separados para casos em que a implementação usa a linguagem de programação Kotlin ou Java e os casos em que ela usa código nativo (C/C++).

Visão geral do SDK do Unity

A API Google Play In-App Update faz parte da família do SDK do Play Core. O plug-in do Unity oferece uma classe AppUpdateManager para lidar com a comunicação entre seu app e a API do Google Play. É necessário instanciar essa classe antes de usá-la para gerenciar atualizações no app:

AppUpdateManager appUpdateManager = new AppUpdateManager();

Configurar o ambiente de desenvolvimento

OpenUPM-CLI

Se a CLI do OpenUPM estiver instalada, você poderá instalar o registro do OpenUPM com o seguinte comando:

openupm add com.google.play.appupdate

OpenUPM

  1. Abra as configurações do gerenciador de pacotes. Para isso, selecione a opção do menu do Unity Edit > Project Settings > Package Manager.

  2. Adicione o OpenUPM como um registro com escopo à janela do gerenciador de pacotes:

    Name: package.openupm.com
    URL: https://package.openupm.com
    Scopes: com.google.external-dependency-manager
      com.google.play.common
      com.google.play.core
      com.google.play.appupdate
    
  3. Selecione a opção do menu do Unity Window > Package Manager para abrir o menu do gerenciador de pacotes.

  4. Defina o menu suspenso de escopo do administrador para selecionar My Registries.

  5. Selecione o pacote Plug-in Google Play Integrity para Unity na lista de pacotes e pressione Instalar.

Importar do GitHub

  1. Faça o download da versão mais recente do .unitypackage no GitHub.

  2. Importe o arquivo .unitypackage selecionando a opção de menu Assets > Import package > Custom Package do Unity e importando todos os itens.

Conferir se há atualizações disponíveis

Antes de solicitar uma atualização, verifique se há alguma disponível para seu app. Use AppUpdateManager para verificar se há uma atualização em uma corrotina:

IEnumerator CheckForUpdate()
{
  PlayAsyncOperation<AppUpdateInfo, AppUpdateErrorCode> appUpdateInfoOperation =
    appUpdateManager.GetAppUpdateInfo();

  // Wait until the asynchronous operation completes.
  yield return appUpdateInfoOperation;

  if (appUpdateInfoOperation.IsSuccessful)
  {
    var appUpdateInfoResult = appUpdateInfoOperation.GetResult();
    // Check AppUpdateInfo's UpdateAvailability, UpdatePriority,
    // IsUpdateTypeAllowed(), ... and decide whether to ask the user
    // to start an in-app update.
  }
  else
  {
    // Log appUpdateInfoOperation.Error.
  }
}

A instância AppUpdateInfo retornada contém o status de disponibilidade da atualização. Se uma atualização no app já estiver em andamento, a instância também vai informar o status dela.

Verificar inatividade de atualização

Além de conferir se uma atualização está disponível, também é possível saber quanto tempo se passou desde que o usuário foi notificado pela última vez sobre uma atualização pela Play Store. Isso pode ajudar você a decidir se deve iniciar uma atualização flexível ou uma imediata. Por exemplo, você pode esperar alguns dias antes de notificar o usuário sobre uma atualização flexível e mais alguns antes de exigir uma imediata.

Use ClientVersionStalenessDays para verificar o número de dias desde que a atualização foi disponibilizada na Google Play Store:

var stalenessDays = appUpdateInfoOperation.ClientVersionStalenessDays;

Verificar prioridade de atualização

Com a API Google Play Developer, é possível definir a prioridade de cada atualização. Isso permite que o app decida como recomendar uma atualização para o usuário. Por exemplo, considere a seguinte estratégia para definir a prioridade de atualização:

  • Pequenas melhorias na IU: atualização de baixa prioridade. Não exigem a atualização flexível nem a imediata.
  • Melhorias de desempenho: atualização de prioridade média. Exigem uma atualização flexível.
  • Atualização crítica de segurança: é de alta prioridade e precisa ser feita de forma imediata.

Para determinar a prioridade, o Google Play usa um valor inteiro entre 0 e 5, sendo 0 o padrão e 5 a prioridade mais alta. Para definir a prioridade de uma atualização, use o campo inAppUpdatePriority em Edits.tracks.releases na API Google Play Developer. Todas as versões recém-adicionadas são consideradas como tendo a mesma prioridade da versão lançada. A prioridade só pode ser definida ao lançar uma nova versão e não pode ser mudada posteriormente.

Defina a prioridade usando a API Google Play Developer, conforme descrito na documentação da API Google Play Developer. A prioridade de atualização no app precisa ser especificada no recurso Edit.tracks transmitido no método Edit.tracks: update. O exemplo a seguir demonstra o lançamento de um app com o código de versão 88 e inAppUpdatePriority 5:

{
  "releases": [{
      "versionCodes": ["88"],
      "inAppUpdatePriority": 5,
      "status": "completed"
  }]
}

No código do app, é possível conferir o nível de prioridade de uma determinada atualização usando UpdatePriority:

var priority = appUpdateInfoOperation.UpdatePriority;

Iniciar uma atualização

Depois de garantir que uma atualização esteja disponível, é possível solicitar uma atualização usando AppUpdateManager.StartUpdate(). Antes de solicitar uma atualização, verifique se você tem um objeto AppUpdateInfo atualizado. Também é necessário criar um objeto AppUpdateOptions para configurar o fluxo de atualização.

O exemplo a seguir cria um objeto AppUpdateOptions para um fluxo de atualização imediata:

// Creates an AppUpdateOptions defining an immediate in-app
// update flow and its parameters.
var appUpdateOptions = AppUpdateOptions.ImmediateAppUpdateOptions();

O exemplo a seguir cria um objeto AppUpdateOptions para um fluxo de atualização flexível:

// Creates an AppUpdateOptions defining a flexible in-app
// update flow and its parameters.
var appUpdateOptions = AppUpdateOptions.FlexibleAppUpdateOptions();

O objeto AppUpdateOptions também contém um campo AllowAssetPackDeletion que define se a atualização tem permissão para limpar pacotes de recursos no caso de armazenamento do dispositivo limitado. Esse campo é definido como false por padrão, mas é possível passar o argumento opcional allowAssetPackDeletion para ImmediateAppUpdateOptions() ou FlexibleAppUpdateOptions() para defini-lo como true:

// Creates an AppUpdateOptions for an immediate flow that allows
// asset pack deletion.
var appUpdateOptions =
  AppUpdateOptions.ImmediateAppUpdateOptions(allowAssetPackDeletion: true);

// Creates an AppUpdateOptions for a flexible flow that allows asset
// pack deletion.
var appUpdateOptions =
  AppUpdateOptions.FlexibleAppUpdateOptions(allowAssetPackDeletion: true);

As próximas etapas dependem do tipo de atualização que você está solicitando: flexível ou imediata.

Processar uma atualização flexível

Depois de ter um objeto AppUpdateInfo atualizado e um objeto AppUpdateOptions configurado corretamente, é possível chamar AppUpdateManager.StartUpdate() para solicitar um fluxo de atualização de forma assíncrona.

IEnumerator StartFlexibleUpdate()
{
  // Creates an AppUpdateRequest that can be used to monitor the
  // requested in-app update flow.
  var startUpdateRequest = appUpdateManager.StartUpdate(
    // The result returned by PlayAsyncOperation.GetResult().
    appUpdateInfoResult,
    // The AppUpdateOptions created defining the requested in-app update
    // and its parameters.
    appUpdateOptions);

  while (!startUpdateRequest.IsDone)
  {
  // For flexible flow,the user can continue to use the app while
  // the update downloads in the background. You can implement a
  // progress bar showing the download status during this time.
  yield return null;
  }

}

Para um fluxo de atualização flexível, é necessário acionar a instalação da atualização do app depois que o download for concluído. Para fazer isso, chame AppUpdateManager.CompleteUpdate(), conforme mostrado no exemplo a seguir:

IEnumerator CompleteFlexibleUpdate()
{
  var result = appUpdateManager.CompleteUpdate();
  yield return result;

  // If the update completes successfully, then the app restarts and this line
  // is never reached. If this line is reached, then handle the failure (e.g. by
  // logging result.Error or by displaying a message to the user).
}

Gerenciar uma atualização imediata

Depois de ter um objeto AppUpdateInfo atualizado e um objeto AppUpdateOptions configurado corretamente, é possível chamar AppUpdateManager.StartUpdate() para solicitar um fluxo de atualização de forma assíncrona.

IEnumerator StartImmediateUpdate()
{
  // Creates an AppUpdateRequest that can be used to monitor the
  // requested in-app update flow.
  var startUpdateRequest = appUpdateManager.StartUpdate(
    // The result returned by PlayAsyncOperation.GetResult().
    appUpdateInfoResult,
    // The AppUpdateOptions created defining the requested in-app update
    // and its parameters.
    appUpdateOptions);
  yield return startUpdateRequest;

  // If the update completes successfully, then the app restarts and this line
  // is never reached. If this line is reached, then handle the failure (for
  // example, by logging result.Error or by displaying a message to the user).
}

Para um fluxo de atualização imediato, o Google Play exibe uma página de confirmação do usuário. Quando o usuário aceitar a solicitação, o Google Play fará o download e a instalação automaticamente da atualização e, em seguida, reiniciará o app para a versão atualizada se a instalação for bem-sucedida.

Tratamento de erros

Esta seção descreve soluções para erros comuns.

  • Se StartUpdate() lançar um ArgumentNullException, isso significa que AppUpdateInfo é nulo. Verifique se o objeto AppUpdateInfo retornado de GetAppUpdateInfo() não é nulo antes de iniciar o fluxo de atualização.
  • Se PlayAsyncOperation retornar o código de erro ErrorUpdateUnavailable, verifique se há uma versão atualizada do app disponível com o mesmo ID do aplicativo e a mesma chave de assinatura.
  • Se PlayAsyncOperation retornar o código de erro ErrorUpdateNotAllowed, significa que o objeto AppUpdateOptions indica um tipo de atualização que não é permitido para a atualização disponível. Verifique se o objeto AppUpdateInfo indica que o tipo de atualização selecionado é permitido antes de iniciar o fluxo de atualização.

Próximas etapas

Teste as atualizações no app para verificar se a integração está funcionando corretamente.