Suporte a atualizações no app (Unreal Engine)

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

Visão geral do SDK do Unreal Engine

A API Play In-App Updates faz parte da família do SDK da Play Core. A API para Unreal Engine oferece uma classe UInAppUpdatesManager para lidar com a comunicação entre seu app e a API do Google Play. Depois que uma solicitação é feita, o app pode verificar o status dela usando EAppUpdateErrorCode.

Versões do Unreal Engine compatíveis

O plug-in é compatível com o Unreal Engine 5.0 e todas as versões posteriores.

Configurar seu ambiente de desenvolvimento

  1. Faça o download do plug-in do Play Unreal Engine (link em inglês) no repositório do GitHub.

  2. Copie a pasta GooglePlay dentro da pasta Plugins no projeto do Unreal Engine.

  3. Abra seu projeto do Unreal Engine e clique em Editar → Plugins.

  4. Pesquise Google Play e marque a caixa de seleção Ativada.

  5. Reinicie o projeto do jogo e acione um build.

  6. Abra o arquivo Build.cs do projeto e adicione o módulo PlayInAppUpdates a PublicDependencyModuleNames:

    using UnrealBuildTool;
    
    public class MyGame : ModuleRules
    {
      public MyGame(ReadOnlyTargetRules Target) : base(Target)
      {
        // ...
    
        PublicDependencyModuleNames.Add("PlayInAppUpdates");
    
        // ...
      }
    }
    

Conferir se há atualizações disponíveis

Antes de solicitar uma atualização, confira se há uma disponível para seu app. Use UInAppUpdatesManager::RequestInfo para verificar se há uma atualização:

MyClass.h

void MyClass::OnRequestInfoOperationCompleted(
  EAppUpdateErrorCode ErrorCode,
  UAppUpdateInfo* UpdateInfo)
{
  // Check the resulting error code.
  if (ErrorCode == EAppUpdateErrorCode::AppUpdate_NO_ERROR)
  {
    // Check AppUpdateInfo's UpdateAvailability, UpdatePriority,
    // IsUpdateTypeAllowed(), ... and decide whether to ask the user
    // to start an in-app update.
  }
}

MyClass.cpp

void MyClass::CheckForUpdateAvailability()
{
  // Create a delegate to bind the callback function.
  FRequestInfoOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnRequestInfoOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnRequestInfoOperationCompleted);

  // Initiate the request info operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->RequestInfo(Delegate);
}

A instância UAppUpdateInfo 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 da atualização em andamento.

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 UAppUpdateInfo:GetClientVersionStalenessDays para verificar o número de dias desde que a atualização foi disponibilizada na Play Store:

int32 ClientVersionStalenessDays = UpdateInfo->GetClientVersionStalenessDays();

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 UAppUpdateInfo::UpdatePriority:

int32 Priority = UpdateInfo->GetPriority();

Iniciar uma atualização

Depois de confirmar que uma atualização está disponível, você pode solicitar uma atualização usando UInAppUpdatesManager::StartUpdate. Antes de solicitar uma atualização, verifique se você tem um objeto UAppUpdateInfo atualizado. Também é necessário criar um objeto UAppUpdateOptions para configurar o fluxo de atualização.

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

// Creates an UAppUpdateOptions defining an immediate in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_IMMEDIATE);

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

// Creates an UAppUpdateOptions defining a flexible in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_FLEXIBLE);

O objeto UAppUpdateOptions também contém uma função IsAssetPackDeletionAllowed que retorna 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 definir o campo usando UAppUpdateOptions::SetAssetPackDeletionAllowed para defini-lo como true:

// Sets the AssetPackDeletionAllowed field to true.
Options->SetAssetPackDeletionAllowed(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 UAppUpdateInfo atualizado e um objeto UAppUpdateOptions configurado corretamente, é possível chamar UInAppUpdatesManager::StartUpdate para solicitar um fluxo de atualização.

MyClass.h

void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

// .cpp
void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);

  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}

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 InAppUpdatesManager::CompleteUpdate, conforme mostrado no exemplo abaixo:

MyClass.h

void MyClass::OnCompleteUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

void MyClass::CompleteFlexibleUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnCompleteUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnCompleteUpdateOperationCompleted);

  // Initiate the complete update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->CompleteUpdate(UpdateInfo, UpdateOptions, Delegate);
}

Gerenciar uma atualização imediata

Depois de ter um objeto UAppUpdateInfo atualizado e um objeto UAppUpdateOptions configurado corretamente, é possível chamar InAppUpdatesManager::StartUpdate para solicitar um fluxo de atualização.

MyClass.h

void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);

  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}

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 UInAppUpdatesManager::StartUpdate retornar um erro AppUpdate_INVALID_REQUEST, significa que UAppUpdateInfo é inválido. Verifique se o objeto UAppUpdateInfo retornado de UInAppUpdatesManager::RequestInfo não é nulo antes de iniciar o fluxo de atualização.
  • Se UInAppUpdatesManager::StartUpdate retornar o erro AppUpdate_NOT_ALLOWED, significa que o objeto UAppUpdateOptions indica um tipo de atualização que não é permitido para a atualização disponível. Confira se o objeto UAppUpdateInfo 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.