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 다운로드

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

이용약관

최종 수정: 2020년 9월 24일
  1. Play Core 소프트웨어 개발 키트를 사용하면 Google API 서비스 약관('API 서비스 약관')과 함께 다음 약관에 동의하는 것으로 간주됩니다. 약관이 상충하는 경우 본 약관이 'API 서비스 약관'보다 우선하여 적용됩니다. 본 약관 및 'API 서비스 약관'을 자세히 읽어 보시기 바랍니다.
  2. 본 약관에서 'API'는 '재배포 가능 코드'를 비롯하여 Google API, 기타 개발자 서비스 및 관련 소프트웨어를 의미합니다.
  3. '재배포 가능 코드'는 Google에서 제공하는 객체 코드 또는 API를 호출하는 헤더 파일입니다.
  4. 본 약관 및 'API 서비스 약관'에 따라 API 클라이언트의 일부로 포함하는 목적으로만 '재배포 가능 코드'를 복사하여 배포할 수 있습니다. Google 및 라이선스 제공자가 '재배포 가능 코드'와 관련된 모든 지적 재산권 및 기타 독점적 권리를 비롯한 모든 권리, 명의 및 이권을 소유합니다. 귀하는 '재배포 가능 코드'를 수정, 번역하거나 재배포 가능 코드의 2차 저작물을 생성할 수 없습니다.
  5. Google에서는 언제든지 통지와 함께 약관을 변경할 수 있으며 변경 후 Play Core 소프트웨어 개발 키트의 사용을 거부할 기회를 제공합니다. Google에서는 https://developer.android.com/guide/playcore/license에서 약관 수정에 관해 통지합니다. 변경사항은 소급 적용되지 않습니다.

다운로드: Play Core Native SDK

다운로드: Play Core Native SDK

play-core-native-sdk-1.11.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 체크섬
    55.6MB 058b4069f09714da938656d43b6dc28d3bc6f821c9d406e9c96a1c3af014dc45
  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/per-feature-proguard-files"
                    ...
                }
                debug {
                    ...
                }
            }
            externalNativeBuild {
                cmake {
                    path 'src/main/CMakeLists.txt'
                }
            }
        }
    
        dependencies {
            // Use the Play Core AAR included with the SDK.
            implementation files("$playcoreDir/playcore.aar")
    
            // Use the following dependency for the Play Integrity API.
            implementation("com.google.android.play:integrity:1.0.0")
            ...
        }
        

    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/per-feature-proguard-files")
                ...
            }
            debug {
                ...
            }
        }
        externalNativeBuild {
            cmake {
                path = "src/main/CMakeLists.txt"
            }
        }
    }
    
    dependencies {
        // Use the Play Core AAR included with the SDK.
        implementation(files("$playcoreDir/playcore.aar"))
        ...
    }
    
  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
            ...)
    

설치 시 제공

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를 반환합니다. 이 유형의 사용 방법에 관한 자세한 내용은 다운로드 정보 확인을 참고하세요.

대용량 다운로드

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

애셋 팩 액세스

다운로드 요청이 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를 테스트합니다.