Suporte para atualizações no app (Unity)

Este guia descreve como oferecer suporte a 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 a implementação usa código nativo (C/C++).

Visão geral do SDK do Unity

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

AppUpdateManager appUpdateManager = new AppUpdateManager();

Configurar seu ambiente de desenvolvimento

OpenUPM-CLI

Se você tiver a CLI do OpenUPM instalada, 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 selecionando a opção de menu do Unity Edit > Project Settings > Package Manager.

  2. Adicione o OpenUPM como um registro de 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. Abra o menu do gerenciador de pacotes selecionando a opção de menu do Unity Window > Package Manager.

  4. Defina o menu suspenso "Escopo do administrador" para selecionar Meus registros.

  5. Selecione o pacote Google Play Integrity plugin for Unity na lista de pacotes e pressione Install.

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 Play Store:

var stalenessDays = appUpdateInfoOperation.ClientVersionStalenessDays;

Verificar prioridade de atualização

A API Google Play Developer permite que você defina a prioridade de cada atualização. Isso permite que o app decida com que intensidade recomendar uma atualização ao 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 espaço de armazenamento limitado no dispositivo. Esse campo é definido como false por padrão, mas é possível transmitir 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 abaixo:

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 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. Confira se o objeto AppUpdateInfo indica que o tipo de atualização selecionado é permitido antes de iniciar o fluxo de atualização.

Próximas etapas

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