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

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 do Unity Assets > Import package > Custom Package e importando todos os itens.

Visão geral do SDK do Unity

A API de atualização no app do Google Play 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();

Verificar a disponibilidade de atualizações

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(), etc. 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;

Conferir 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 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 espaço de armazenamento limitado no dispositivo. 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 em vez disso:

// 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 da solicitação de uma atualização flexível ou de uma atualização 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.

A seguir

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