Asset Delivery 통합(네이티브)

이 가이드의 단계에 따라 C 및 C++ 코드에서 앱의 애셋 팩에 액세스하세요.

샘플 통합 코드는 GitHub에서 확인할 수 있습니다.

네이티브용 빌드

프로젝트의 Android App Bundle에 Play Asset Delivery를 빌드하려면 다음 단계를 따르세요. 이러한 단계를 진행하는 데 Android 스튜디오를 사용할 필요는 없습니다.

  1. 프로젝트의 build.gradle 파일에서 Android Gradle 플러그인 버전을 4.0.0 이상으로 업데이트합니다.

  2. 프로젝트의 최상위 디렉터리에 애셋 팩용 디렉터리를 생성합니다. 이 디렉터리 이름은 애셋 팩 이름으로 사용됩니다. 애셋 팩 이름은 문자로 시작되어야 하며 문자, 숫자 및 밑줄만 포함할 수 있습니다.

  3. 애셋 팩 디렉터리에서 build.gradle 파일을 만들고 다음 코드를 추가합니다. 애셋 팩 이름과 하나의 전송 유형만 지정해야 합니다.

    // In the asset pack’s build.gradle file:
    plugins {
        id 'com.android.asset-pack'
    }
    
    assetPack {
        packName = "asset-pack-name" // Directory name for the asset pack
        dynamicDelivery {
            deliveryType = "[ install-time | fast-follow | on-demand ]"
        }
    }
    
  4. 프로젝트의 앱 build.gradle 파일에서 아래와 같이 프로젝트의 모든 애셋 팩 이름을 추가합니다.

    // In the app build.gradle file:
    android {
        ...
        assetPacks = [":asset-pack-name", ":asset-pack2-name"]
    }
    
  5. 프로젝트의 settings.gradle 파일에서 아래와 같이 프로젝트의 모든 애셋 팩을 포함합니다.

    // In the settings.gradle file:
    include ':app'
    include ':asset-pack-name'
    include ':asset-pack2-name'
    
  6. 애셋 팩 디렉터리에 하위 디렉터리(src/main/assets)를 만듭니다.

  7. 애셋을 src/main/assets 디렉터리에 배치합니다. 여기에도 하위 디렉터리를 만들 수 있습니다. 이제 앱의 디렉터리 구조는 다음과 같습니다.

    • build.gradle
    • settings.gradle
    • app/
    • asset-pack-name/build.gradle
    • asset-pack-name/src/main/assets/your-asset-directories
  8. Gradle로 Android App Bundle을 빌드합니다. 생성된 App Bundle에서 루트 수준 디렉터리에는 이제 다음이 포함됩니다.

    • asset-pack-name/manifest/AndroidManifest.xml: 애셋 팩의 식별자 및 전송 모드를 구성합니다.
    • asset-pack-name/assets/your-asset-directories: 애셋 팩의 일부로 제공되는 모든 애셋이 포함된 디렉터리

    Gradle은 각 애셋 팩의 매니페스트를 생성하고 assets/ 디렉터리를 자동으로 출력합니다.

  9. (선택사항) 다양한 텍스처 압축 형식을 지원하도록 App Bundle을 구성합니다.

Play Asset Delivery 라이브러리와 통합

액세스하려는 애셋 팩의 전송 유형에 따라 이 API를 구현합니다. 이러한 단계는 다음 플로우 차트에 나와 있습니다.

네이티브 코드의 애셋 팩 흐름 다이어그램

그림 1. 애셋 팩 액세스 흐름 다이어그램

Play Core Native SDK는 애셋 팩을 요청하고 다운로드를 관리하며 애셋에 액세스하기 위해 C 헤더 파일 play/asset_pack.h를 제공합니다.

Play Core Native SDK의 개발 환경 설정

다운로드 Play Core Native SDK

다운로드하기 전에 다음 이용약관에 동의해야 합니다.

이용약관

Last modified: September 24, 2020
  1. By using the Play Core Software Development Kit, you agree to these terms in addition to the Google APIs Terms of Service ("API ToS"). If these terms are ever in conflict, these terms will take precedence over the API ToS. Please read these terms and the API ToS carefully.
  2. For purposes of these terms, "APIs" means Google's APIs, other developer services, and associated software, including any Redistributable Code.
  3. “Redistributable Code” means Google-provided object code or header files that call the APIs.
  4. Subject to these terms and the terms of the API ToS, you may copy and distribute Redistributable Code solely for inclusion as part of your API Client. Google and its licensors own all right, title and interest, including any and all intellectual property and other proprietary rights, in and to Redistributable Code. You will not modify, translate, or create derivative works of Redistributable Code.
  5. Google may make changes to these terms at any time with notice and the opportunity to decline further use of the Play Core Software Development Kit. Google will post notice of modifications to the terms at https://developer.android.com/guide/playcore/license. Changes will not be retroactive.
다운로드 Play Core Native SDK

play-core-native-sdk-1.14.0.zip

  1. 다음 중 하나를 실행합니다.

    • Android 스튜디오 버전 4.0 이상을 설치합니다. SDK Manager UI를 사용하여 Android SDK 플랫폼 버전 10.0(API 수준 29)을 설치합니다.
    • Android SDK 명령줄 도구를 설치하고 sdkmanager를 사용하여 Android SDK 플랫폼 버전 10.0(API 수준 29)을 설치합니다.
  2. SDK Manager를 사용하여 최신 CMake 및 Android 네이티브 개발 키트(NDK)를 설치함으로써 네이티브 개발을 위해 Android 스튜디오를 준비합니다. 네이티브 프로젝트를 만들거나 가져오는 방법에 관한 자세한 내용은 NDK 시작하기를 참고하세요.

  3. ZIP 파일을 다운로드하여 프로젝트와 함께 압축을 풉니다.

    다운로드 링크 크기 SHA-256 체크섬
    36MiB 782a8522d937848c83a715c9a258b95a3ff2879a7cd71855d137b41c00786a5e
  4. 아래와 같이 앱의 build.gradle 파일을 업데이트합니다.

    Groovy

        // App build.gradle
    
        plugins {
          id 'com.android.application'
        }
    
        // Define a path to the extracted Play Core SDK files.
        // If using a relative path, wrap it with file() since CMake requires absolute paths.
        def playcoreDir = file('../path/to/playcore-native-sdk')
    
        android {
            defaultConfig {
                ...
                externalNativeBuild {
                    cmake {
                        // Define the PLAYCORE_LOCATION directive.
                        arguments "-DANDROID_STL=c++_static",
                                  "-DPLAYCORE_LOCATION=$playcoreDir"
                    }
                }
                ndk {
                    // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                    abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                }
            }
            buildTypes {
                release {
                    // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                    proguardFile '$playcoreDir/proguard/common.pgcfg'
                    proguardFile '$playcoreDir/proguard/gms_task.pgcfg'
                    proguardFile '$playcoreDir/proguard/per-feature-proguard-files'
                    ...
                }
                debug {
                    ...
                }
            }
            externalNativeBuild {
                cmake {
                    path 'src/main/CMakeLists.txt'
                }
            }
        }
    
        dependencies {
            // Import these feature-specific AARs for each Google Play Core library.
            implementation 'com.google.android.play:app-update:2.0.0'
            implementation 'com.google.android.play:asset-delivery:2.0.0'
            implementation 'com.google.android.play:integrity:1.0.1'
            implementation 'com.google.android.play:review:2.0.0'
    
            // Import these common dependencies.
            implementation 'com.google.android.gms:play-services-tasks:18.0.2'
            implementation files("$playcoreDir/playcore-native-metadata.jar")
            ...
        }
        

    Kotlin

    // App build.gradle
    
    plugins {
        id("com.android.application")
    }
    
    // Define a path to the extracted Play Core SDK files.
    // If using a relative path, wrap it with file() since CMake requires absolute paths.
    val playcoreDir = file("../path/to/playcore-native-sdk")
    
    android {
        defaultConfig {
            ...
            externalNativeBuild {
                cmake {
                    // Define the PLAYCORE_LOCATION directive.
                    arguments += listOf("-DANDROID_STL=c++_static", "-DPLAYCORE_LOCATION=$playcoreDir")
                }
            }
            ndk {
                // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                abiFilters.clear()
                abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
            }
        }
        buildTypes {
            release {
                // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                proguardFile("$playcoreDir/proguard/common.pgcfg")
                proguardFile("$playcoreDir/proguard/gms_task.pgcfg")
                proguardFile("$playcoreDir/proguard/per-feature-proguard-files")
                ...
            }
            debug {
                ...
            }
        }
        externalNativeBuild {
            cmake {
                path = "src/main/CMakeLists.txt"
            }
        }
    }
    
    dependencies {
        // Import these feature-specific AARs for each Google Play Core library.
        implementation("com.google.android.play:app-update:2.0.0")
        implementation("com.google.android.play:asset-delivery:2.0.0")
        implementation("com.google.android.play:integrity:1.0.1")
        implementation("com.google.android.play:review:2.0.0")
    
        // Import these common dependencies.
        implementation("com.google.android.gms:play-services-tasks:18.0.2")
        implementation(files("$playcoreDir/playcore-native-metadata.jar"))
        ...
    }
    
  5. 아래와 같이 앱의 CMakeLists.txt 파일을 업데이트합니다.

    cmake_minimum_required(VERSION 3.6)
    
    ...
    
    # Add a static library called “playcore” built with the c++_static STL.
    include(${PLAYCORE_LOCATION}/playcore.cmake)
    add_playcore_static_library()
    
    // In this example “main” is your native code library, i.e. libmain.so.
    add_library(main SHARED
            ...)
    
    target_include_directories(main PRIVATE
            ${PLAYCORE_LOCATION}/include
            ...)
    
    target_link_libraries(main
            android
            playcore
            ...)
    

데이터 수집

Play Core Native SDK는 Google에서 제품을 개선할 수 있도록 다음과 같은 버전 관련 데이터를 수집할 수 있습니다.

  • 앱의 패키지 이름
  • 앱의 패키지 버전
  • Play Core Native SDK 버전

이 데이터는 앱 패키지를 Play Console에 업로드할 때 수집됩니다. 이 데이터 수집 프로세스를 선택 해제하려면 build.gradle 파일에서 $playcoreDir/playcore-native-metadata.jar 가져오기를 삭제합니다.

Play Core Native SDK 사용 및 Google의 수집된 데이터 사용과 관련된 이 데이터 수집은 앱 패키지를 Play Console에 업로드할 때 Gradle에 선언된 라이브러리 종속 항목에 관한 Google의 수집과는 별개이며 관련이 없습니다.

설치 시 제공

install-time으로 구성된 애셋 팩은 앱 실행 시 즉시 사용할 수 있습니다. NDK AAssetManager API를 사용하여 이 모드에서 제공되는 애셋에 액세스하세요.

#include <android/asset_manager.h>
#include <android_native_app_glue.h>
...
AAssetManager* assetManager = app->activity->assetManager;
AAsset* asset = AAssetManager_open(assetManager, "asset-name", AASSET_MODE_BUFFER);
size_t assetLength = AAsset_getLength(asset);
char* buffer = (char*) malloc(assetLength + 1);
AAsset_read(asset, buffer, assetLength);

빠른 추적 및 주문형 제공

다음 섹션에서는 API 초기화 방법, 다운로드하기 전에 애셋 팩 정보를 확인하는 방법, API를 호출하여 다운로드를 시작하는 방법, 다운로드한 팩에 액세스하는 방법을 보여줍니다. 이 섹션은 fast-followon-demand 애셋 팩에 적용됩니다.

앱 실행

다른 함수를 호출하기 전에 항상 AssetPackManager_init()를 호출하여 애셋 팩 API를 초기화합니다. 애셋 팩 오류 코드가 있는지 확인합니다.

#include "play/asset_pack.h"
...
AssetPackErrorCode AssetPackManager_init(JavaVM* jvm, jobject android_context);

ANativeActivityCallbacksonPause()onResume()에서 다음 함수도 호출해야 합니다.

애셋 팩 다운로드 정보 확인

앱은 애셋 팩을 가져오기 전에 다운로드 크기를 공개해야 합니다. AssetPackManager_requestInfo() 함수를 사용하여 다운로드 크기 및 팩이 이미 다운로드되고 있는지를 비동기식으로 요청합니다. 그런 다음 AssetPackManager_getDownloadState()를 사용하여 다운로드 상태를 폴링합니다(예: 게임 루프의 프레임당 이 함수를 한 번 호출). 요청이 실패하면 애셋 팩 오류 코드를 확인하세요.

AssetPackErrorCode AssetPackManager_requestInfo();      // Call once
AssetPackErrorCode AssetPackManager_getDownloadState(); // Call once per frame in your game loop

AssetPackManager_getDownloadState() 함수는 불투명 유형 AssetPackDownloadState를 출력 포인터로 반환합니다. 이 포인터를 사용하여 다음 함수를 호출하세요.

AssetPackDownloadState* state;
AssetPackErrorCode error_code = AssetPackManager_getDownloadState(asset-pack-name, &state);
AssetPackDownloadStatus status = AssetPackDownloadState_getStatus(state);
uint64_t downloadedBytes = AssetPackDownloadState_getBytesDownloaded(state);
uint64_t totalBytes = AssetPackDownloadState_getTotalBytesToDownload(state));
AssetPackDownloadState_destroy(state);

설치

AssetPackManager_requestDownload()를 사용하여 처음으로 애셋 팩 다운로드를 시작하거나 애셋 팩 업데이트 완료를 요청합니다.

AssetPackErrorCode AssetPackManager_requestDownload();  // Call once
AssetPackErrorCode AssetPackManager_getDownloadState(); // Call once per frame in your game loop

AssetPackManager_getDownloadState() 함수는 불투명 유형 AssetPackDownloadState를 반환합니다. 이 유형의 사용 방법에 관한 자세한 내용은 다운로드 정보 확인을 참고하세요.

대용량 다운로드

다운로드 용량이 200MB보다 크고 사용자가 Wi-Fi에 연결되어 있지 않은 경우 사용자가 모바일 데이터 연결을 사용하여 다운로드를 진행하는 데 명시적으로 동의할 때까지 다운로드가 시작되지 않습니다. 마찬가지로 다운로드 용량이 크고 사용자의 Wi-Fi 연결이 끊기면 다운로드는 일시중지되며 모바일 데이터 연결을 사용하여 계속 진행하는 데는 명시적 동의가 필요합니다. 일시중지된 팩의 상태는 WAITING_FOR_WIFI입니다. 사용자에게 동의 요청 메시지를 표시하는 UI 흐름을 트리거하려면 다음을 사용하세요.

필수 사용자 확인

팩이 REQUIRES_USER_CONFIRMATION 상태이면 사용자가 AssetPackManager_showConfirmationDialog()로 표시된 대화상자를 수락할 때까지 다운로드가 진행되지 않습니다. 이 상태는 Play에서 앱을 인식하지 못하면 발생할 수 있습니다. 이 경우 AssetPackManager_showConfirmationDialog()를 호출하면 앱이 업데이트됩니다. 업데이트 후 애셋을 다시 요청하세요.

애셋 팩 액세스

다운로드 요청이 COMPLETED 상태에 도달하면 파일 시스템 호출을 사용하여 애셋 팩에 액세스할 수 있습니다. 각 애셋 팩은 앱의 내부 저장소에 있는 별도의 디렉터리에 저장됩니다. AssetPackManager_getAssetPackLocation()을 사용하여 지정된 애셋 팩의 AssetPackLocation을 가져옵니다. 가져온 위치에서 AssetPackLocation_getStorageMethod()를 사용하여 저장 방법을 확인합니다.

  • ASSET_PACK_STORAGE_APK: 애셋 팩이 APK로 설치됩니다. 이러한 애셋에 액세스하려면 설치 시 제공을 참고하세요.
  • ASSET_PACK_STORAGE_FILES: AssetPackLocation_getAssetsPath()를 사용하여 애셋이 포함된 디렉터리의 파일 경로를 가져오거나 애셋이 다운로드되지 않은 경우 null을 가져옵니다. 이 파일 경로로 다운로드한 파일을 수정하지 마세요.
AssetPackLocation* location;

AssetPackErrorCode error_code = AssetPackManager_getAssetPackLocation(asset-pack-name, &location);

if (error_code == ASSET_PACK_NO_ERROR) {
    AssetPackStorageMethod storage_method = AssetPackLocation_getStorageMethod(location);
    const char* assets_path = AssetPackLocation_getAssetsPath(location);
    AssetPackLocation_destroy(location);
}

애셋을 찾으면 fopen 또는 ifstream과 같은 함수를 사용하여 파일에 액세스합니다.

기타 Play Core API 메서드

다음은 앱에서 사용해 볼 수 있는 추가 API 메서드입니다.

요청 취소

AssetPackManager_cancelDownload()를 사용하여 활성 상태의 애셋 팩 요청을 취소할 수 있습니다. 이 요청이 최선의 작업입니다.

삭제 요청

AssetPackManager_requestRemoval()을 사용하여 애셋 팩 삭제를 예약합니다.

다음 단계

로컬 및 Google Play에서 Play Asset Delivery를 테스트합니다.