인앱 업데이트 지원(네이티브)

이 가이드에서는 네이티브 코드(C 또는 C++)를 사용하여 앱에서 인앱 업데이트를 지원하는 방법을 설명합니다. Kotlin 프로그래밍 언어 또는 자바 프로그래밍 언어를 사용하는 구현과 Unity를 사용하는 구현을 위한 별도의 가이드가 있습니다.

Native SDK 개요

Play Core Native SDK는 Play Core SDK 제품군의 일부입니다. Native SDK에는 Java Play Core SDK에서 AppUpdateManager를 래핑하는 C 헤더 파일 app_update.h가 포함되어 있습니다. 이 헤더 파일을 사용하면 앱이 네이티브 코드에서 직접 인앱 업데이트를 진행하기 위해 API를 호출할 수 있습니다.

개발 환경 설정

개발 환경을 설정하려면 Play Core 라이브러리 가이드에 있는 네이티브 섹션의 설정 안내를 따릅니다.

Play Core Native SDK를 프로젝트에 통합한 후 API 호출이 포함된 파일에 다음 라인을 포함합니다.

#include "play/app_update.h"

인앱 업데이트 API 초기화

android_native_app_glue.h로 빌드된 다음 예에 나와 있는 것처럼 인앱 업데이트 API를 사용할 때마다 먼저 AppUpdateManager_init() 함수를 호출하여 이 API를 초기화합니다.

void android_main(android_app* app) {
  app->onInputEvent = HandleInputEvent;

  AppUpdateErrorCode error_code =
    AppUpdateManager_init(app->activity->vm, app->activity->clazz);
  if (error_code == APP_UPDATE_NO_ERROR) {
    // You can use the API.
  }
}

업데이트 사용 가능 여부 확인

업데이트를 요청하기 전에 앱에 사용할 수 있는 업데이트가 있는지 확인합니다. AppUpdateManager_requestInfo()가 이후에 인앱 업데이트 흐름을 시작하는 데 필요한 정보를 수집하는 비동기식 요청을 시작합니다. 요청이 시작되면 이 함수가 APP_UPDATE_NO_ERROR를 반환합니다.

AppUpdateErrorCode error_code = AppUpdateManager_requestInfo()

if (error_code == APP_UPDATE_NO_ERROR) {
    // The request has successfully started, check the result using
    // AppUpdateManager_getInfo.
}

AppUpdateManager_getInfo()를 사용하여 진행 중인 프로세스와 요청 결과를 추적할 수 있습니다. 오류 코드 외에 이 함수는 업데이트 요청에 관한 정보를 검색하는 데 사용할 수 있는 AppUpdateInfo 불투명 구조체를 반환합니다. 예를 들어 이 함수가 info와 관련해 null이 아닌 결과를 반환할 때까지 다음과 같이 모든 게임 루프에서 이 함수를 호출하는 것이 좋습니다.

AppUpdateInfo* info;
GameUpdate() {

   // Keep calling this in every game loop until info != nullptr
   AppUpdateErrorCode error_code = AppUpdateManager_getInfo(&info);

   if (error_code == APP_UPDATE_NO_ERROR && info != nullptr) {
       // Successfully started, check the result in the following functions
   }
...
}

업데이트 비활성화 확인

업데이트 사용 가능 여부를 확인하는 것 외에 Play 스토어를 통해 사용자에게 업데이트 알림이 전송된 후 얼마나 시간이 지났는지 확인하는 것도 좋습니다. 그렇게 하면 유연한 업데이트를 시작할지 아니면 즉시 업데이트를 시작할지 판단하는 데 도움이 될 수 있습니다. 예를 들어 며칠을 기다렸다가 사용자에게 유연한 업데이트를 알린 다음 며칠 후 즉시 업데이트를 요청할 수도 있습니다.

Play 스토어를 통해 업데이트가 제공된 후 경과한 일수를 확인하려면 AppUpdateInfo_getClientVersionStalenessDays()를 사용합니다.

int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);

업데이트 우선순위 확인

Google Play Developer API를 사용하여 각 업데이트의 우선순위를 설정할 수 있습니다. 이렇게 하면 앱에서 사용자에게 업데이트를 얼마나 강력하게 권장할지 결정할 수 있습니다. 업데이트 우선순위를 설정하는 다음 전략을 예로 들어 보겠습니다.

  • 사소한 UI 개선: 낮은 우선순위 업데이트. 유연한 업데이트와 즉시 업데이트를 둘 다 요청하지 않습니다. 사용자가 앱과 상호작용하지 않을 때만 업데이트합니다.
  • 성능 개선: 중간 우선순위 업데이트. 유연한 업데이트를 요청합니다.
  • 중요 보안 업데이트: 높은 우선순위 업데이트. 즉시 업데이트를 요청합니다.

우선순위를 결정하기 위해 Google Play는 0에서 5 사이의 정숫값을 사용합니다. 0은 기본값, 5는 가장 높은 우선순위입니다. 업데이트 우선순위를 설정하려면 Google Play Developer API의 Edits.tracks.releases 아래에 있는 inAppUpdatePriority 필드를 사용하세요. 출시에 새로 추가된 모든 버전은 출시와 동일한 우선순위로 간주됩니다. 우선순위는 새 버전을 출시할 때만 설정할 수 있으며 나중에 변경할 수 없습니다.

Play Developer API 문서에 설명된 대로 Google Play Developer API를 사용하여 우선순위를 설정합니다. Edit.tracks: update 메서드에 전달된 Edit.tracks 리소스에서 인앱 업데이트 우선순위를 지정합니다. 다음 예는 버전 코드가 88이고 inAppUpdatePriority가 5인 앱 출시를 보여 줍니다.

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

앱 코드에서 AppUpdateInfo_getPriority()를 사용하여 특정 업데이트의 우선순위를 확인할 수 있습니다.

int32_t priority = AppUpdateInfo_getPriority(info);

업데이트 시작

업데이트가 있다는 것을 확인한 후 AppUpdateManager_requestStartUpdate()를 사용하여 업데이트를 요청할 수 있습니다. 업데이트를 요청하기 전에 최신 AppUpdateInfo 객체를 가져오고 AppUpdateOptions 객체를 만들어 업데이트 흐름을 구성합니다. AppUpdateOptions 객체는 유연한 업데이트와 즉시 업데이트 중 어떤 업데이트여야 하는지를 비롯해 인앱 업데이트 흐름의 옵션을 정의합니다.

다음 예에서는 유연한 업데이트 흐름을 위한 AppUpdateOptions 객체를 만듭니다.

// Creates an AppUpdateOptions configuring a flexible in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_FLEXIBLE, &options);

다음 예에서는 즉시 업데이트 흐름을 위한 AppUpdateOptions 객체를 만듭니다.

// Creates an AppUpdateOptions configuring an immediate in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_IMMEDIATE, &options);

AppUpdateOptions 객체에는 기기 저장용량이 제한된 경우 업데이트가 애셋 팩을 지울 수 있는지 정의하는 AllowAssetPackDeletion 필드도 포함되어 있습니다. 이 필드는 기본적으로 false로 설정되지만 AppUpdateOptions_setAssetPackDeletionAllowed() 메서드를 사용하여 true로 대신 설정할 수 있습니다.

bool allow = true;
AppUpdateErrorCode error_code = AppUpdateOptions_setAssetPackDeletionAllowed(options, allow);

최신 AppUpdateInfo 객체와 적절히 구성된 AppUpdateOptions 객체가 있으면 AppUpdateManager_requestStartUpdate()를 호출하여 비동기식으로 업데이트 흐름을 요청하고 마지막 매개변수에 Android 액티비티 jobject를 전달합니다.

AppUpdateErrorCode request_error_code =
AppUpdateManager_requestStartUpdate(info, options, app->activity->clazz);

리소스를 확보하려면 AppUpdateInfo_destroy()AppUpdateOptions_destroy()를 호출하여 더 이상 필요하지 않은 AppUpdateInfoAppUpdateOptions의 인스턴스를 각각 해제합니다.

AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);

즉시 업데이트 흐름에서는 Google Play에서 사용자 확인 페이지를 표시합니다. 사용자가 요청을 수락하면 Google Play는 포그라운드에 업데이트를 자동으로 다운로드하고 설치한 다음 설치가 완료되면 업데이트된 버전으로 앱을 다시 시작합니다.

유연한 업데이트 흐름에서는 사용자가 앱과 계속 상호작용하는 동안 현재 업데이트 상태를 추적할 수 있도록 최신 AppUpdateInfo 객체를 지속적으로 요청할 수 있습니다. 다운로드가 완료되면 다음 예에서와 같이 AppUpdateManager_requestCompleteUpdate()를 호출하여 업데이트 완료를 트리거해야 합니다.

AppUpdateStatus status = AppUpdateInfo_getStatus(info);
if (status == APP_UPDATE_DOWNLOADED) {
    AppUpdateErrorCode error_code = AppUpdateManager_requestCompleteUpdate();
    if (error_code != APP_UPDATE_NO_ERROR)
    {
      // There was an error while completing the update flow.
    }
}

앱에서 API 사용을 마치면 AppUpdateManager_destroy() 함수를 호출하여 리소스를 해제합니다.

오류 처리

이 섹션에서는 특정 AppUpdateErrorCode 값으로 표시된 일반적인 오류에 대한 해결책을 설명합니다.

  • -110, APP_UPDATE_INITIALIZATION_NEEDED의 오류 코드는 API가 제대로 초기화되지 않았음을 나타냅니다. AppUpdateManager_init()를 호출하여 API를 초기화합니다.
  • -4, APP_UPDATE_INVALID_REQUEST의 오류 코드는 업데이트 흐름 요청의 일부 매개변수 형식이 잘못되었음을 나타냅니다. AppUpdateInfoAppUpdateOptions 객체가 null이 아니며 올바른 형식인지 확인합니다.
  • -5, APP_UPDATE_UNAVAILABLE의 오류 코드는 적용 가능한 업데이트가 없음을 나타냅니다. 타겟 버전의 패키지 이름애플리케이션 ID, 서명 키가 동일한지 확인합니다. 사용 가능한 업데이트가 있으면 앱의 캐시를 지우고 AppUpdateManager_requestAppUpdateInfo()를 다시 호출하여 AppUpdateInfo를 새로 고칩니다.
  • -6, APP_UPDATE_NOT_ALLOWED의 오류 코드는 AppUpdateOption 객체로 표시된 업데이트 유형이 허용되지 않음을 나타냅니다. 업데이트 흐름을 시작하기 전에 업데이트 유형이 허용되는 것으로 AppUpdateInfo 객체에 나타나는지 확인합니다.

다음 단계

통합이 제대로 작동하는지 확인하기 위해 앱의 인앱 업데이트를 테스트합니다.