빠른 시작: Android
Android용 PlayFab 서비스 SDK를 시작합니다. 다음 단계에 따라 프로젝트에 라이브러리를 포함하고 기본 PlayFab 기능에 대한 샘플 코드를 사용해 보세요.
이 빠른 시작은 Android SDK를 사용하여 첫 번째 PlayFab API 호출을 만드는 데 도움이 됩니다. 계속하기 전에 PlayFab 계정이 있고 PlayFab 게임 관리자에 익숙한 빠른 시작: 게임 관리자의 단계를 완료했는지 확인합니다.
요구 사항
- PlayFab 개발자 계정입니다.
- Android Studio가 설치되었습니다.
프로젝트 설정
PlayFab SDK 릴리스 페이지에서 PlayFab Android SDK 프로젝트에 다운로드합니다.
사용자 고유의 프로젝트에 PlayFab C SDK 통합
다음 단계는 Android Studio를 사용하여 새 프로젝트를 만들었다는 가정 하에 작성되었습니다.
게임에 이진 파일 추가
프로젝트에 통합해야 하는 이진 파일의 두 부분인 공유 개체 파일(.so)과 Android 보관 파일(.aar)이 있습니다. 이진 파일을 직접 빌드하거나 릴리스 페이지에서 다운로드할 수 있습니다.
.so 파일 추가
이러한 파일은 CMake를 사용하여 프로젝트에 통합됩니다.
Android용 PlayFab SDK 릴리스의 압축을 풀고 원하는 디렉터리에 콘텐츠를 배치합니다.
target_include_directories 또는 이와 동등한 다른 함수를 사용하여 PlayFab SDK 릴리스에서 이 헤더 목록을 추가합니다.
TARGET_INCLUDE_DIRECTORIES(
${PROJECT_NAME}
"Include"
)
target_link_libraries 또는 이와 동등한 다른 함수를 사용하여 프로젝트에 .so 파일의 위치를 연결합니다.
예:
set(PLAYFAB_SERVICES_PATH "[LOCATION OF YOUR FILE]/libPlayFabServices.Android.so")
set(PLAYFAB_CORE_PATH "[LOCATION OF YOUR FILE]/libPlayFabCore.Android.so")
set(LIBHTTPCLIENT_PATH "[LOCATION OF YOUR FILE]/libHttpClient.Android.so")
TARGET_LINK_LIBRARIES(
[YOUR PROJECT NAME]
${PLAYFAB_SERVICES_PATH}
${PLAYFAB_CORE_PATH}
${LIBHTTPCLIENT_PATH}
)
.aar 파일 추가
이러한 파일은 Gradle을 사용하여 프로젝트에 통합됩니다.
- 앱 수준 Android 프로젝트 디렉터리 내에 libs 폴더를 만듭니다. 프로젝트 디렉터리가 지금 어떻게 표시되어야 하는지에 대한 예는 다음과 같습니다.
.aar 파일을 libs 폴더에 복사합니다.
앱 수준 build.gradle 파일에서 libs 폴더와 동일한 디렉터리에 있는 파일을 종속성 섹션에 추가합니다. 두 번째 줄은 libHttpClient에 대한 종속성으로 필요합니다.
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
초기화 및 로그인
Android용 PlayFab 서비스 SDK를 사용하도록 프로젝트가 완전히 설정되었으므로 다음 단계에 따라 몇 가지 샘플 호출이 작동합니다.
초기 설정
먼저 Android 활동의 인스턴스를 포함하도록 애플리케이션을 설정해야 합니다. 또한 JNI(Java 네이티브 인터페이스)와 함께 NDK를 사용하려면 작은 C/C++ 애플리케이션을 설정해야 합니다. 다음은 https://github.com/android/ndk-samples/tree/android-mk/hello-jni 참조에 대한 작은 예입니다.
이 예제에는 jstring을 반환하는 네이티브 메서드가 포함되어 있습니다.
jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env, jobject thiz)
네이티브 메서드를 사용하여 JAVA VM 및 애플리케이션 컨텍스트를 가져올 수 있습니다. PFServices를 초기화하는 데 필요한 두 가지 사항이 있습니다. 초기화를 위해 유사한 메서드를 만들 수 있습니다.
void Java_com_example_hellojni_HelloJni_InitializeApp(JNIEnv* env, jobject appContext)
그런 다음 JNIEnv 변수를 사용하여 Java VM을 검색할 수 있습니다.
JavaVM* javaVM = nullptr;
jint res = env->GetJavaVM(&javaVM);
if (res != JNI_OK)
{
// error handling
}
다음으로, jobject 매개 변수를 사용하여 애플리케이션 컨텍스트를 받을 수 있습니다.
applicationContext = env->NewGlobalRef(appContext);
이제 이 두 변수를 저장했으므로 호출을 시작할 수 있습니다.
헤더
포함된 모든 PlayFab 기능에 액세스하려면 PFServices.h를 포함합니다.
#include <playfab/services/PFServices.h>
초기화
PlayFab 초기화에는 두 가지 함수 호출(PFServicesInitialize 및 PFServiceConfigCreateHandle)이 필요합니다. 이 초기화의 결과는 PFServiceConfigHandle입니다. 후속 로그인 호출에 이 핸들을 제공하여 호출을 PlayFab 백엔드의 올바른 제목으로 지정합니다.
HCInitArgs initArgs;
// Use the Java VM and application context from earlier
initArgs.javaVM = javaVm;
initArgs.applicationContext = applicationContext;
HRESULT hr = PFServicesInitialize(nullptr, &initArgs); // Add your own error handling when FAILED(hr) == true
PFServiceConfigHandle serviceConfigHandle{ nullptr };
hr = PFServiceConfigCreateHandle(
"https://ABCDEF.playfabapi.com", // PlayFab API endpoint - obtained in the Game Manager
"ABCDEF", // PlayFab Title id - obtained in the Game Manager
&serviceConfigHandle);
로그인
PFServiceConfigHandle이 있으면 이를 사용하여 플레이어 로그인 호출을 할 수 있습니다. SDK에서 PFAuthenticationLoginWithCustomIDAsync 같은 PFAuthenticationLoginWith*Async 메서드를 사용합니다. 이 기능을 사용하면, 사용자 지정 ID를 통해 PlayFab에 플레이어를 로그인할 수 있습니다.
로그인 호출을 한 후 XAsyncGetStatus로 호출 상태를 확인할 수 있습니다. 상태는 E_PENDING으로 시작하고 통화가 성공적으로 완료되면 S_OK로 변경됩니다. 어떤 이유로 호출이 실패하면 상태에 해당 실패가 반영됩니다. 모든 PlayFab 서비스 호출에 대한 오류 처리는 이 방식으로 작동합니다.
S_OK 결과와 함께 PFEntityHandle을 반환합니다. 이 핸들을 사용하여 로그인한 플레이어로 후속 PlayFab 호출을 수행합니다. 여기에는 해당 플레이어로 PlayFab 서비스를 인증하는 데 필요한 모든 자료가 포함됩니다.
PFAuthenticationLoginWithCustomIDRequest request{};
request.createAccount = true;
request.customId = "player1";
XAsyncBlock async{};
HRESULT hr = PFAuthenticationLoginWithCustomIDAsync(serviceConfigHandle, &request, &async); // Add your own error handling when FAILED(hr) == true
hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
std::vector<char> loginResultBuffer;
PFAuthenticationLoginResult const* loginResult;
size_t bufferSize;
hr = PFAuthenticationLoginWithCustomIDGetResultSize(&async, &bufferSize);
loginResultBuffer.resize(bufferSize);
PFEntityHandle entityHandle{ nullptr };
hr = PFAuthenticationLoginWithCustomIDGetResult(&async, &entityHandle, loginResultBuffer.size(), loginResultBuffer.data(), &loginResult, nullptr);
서비스 호출
플레이어를 로그인한 후 이제 PlayFab 백 엔드를 호출할 수 있습니다. 다음은 현재 플레이어에 대해 PlayFab에 저장된 파일을 가져오기 위한 호출의 예입니다.
EntityKey 가져오기
PlayFab에 대한 일부 호출에 유용할 수 있는 한 가지는 플레이어의 PFEntityKey를 아는 것입니다. PFEntityToken이 있으면 PFEntityGetEntityKey를 사용하여 PFEntityKey를 검색할 수 있습니다.
PFEntityKey const* pEntityKey{};
std::vector<char> entityKeyBuffer;
size_t size{};
HRESULT hr = PFEntityGetEntityKeySize(entityHandle, &size); // Add your own error handling when FAILED(hr) == true
entityKeyBuffer.resize(size);
hr = PFEntityGetEntityKey(entityHandle, entityKeyBuffer.size(), entityKeyBuffer.data(), &pEntityKey, nullptr);
GetFile 호출
모든 PlayFab 호출은 요청 개체 준비, 호출 만들기(로그인에서 PFEntityHandle 사용), 응답을 받을 개체 만들기 및 GetResult 함수를 호출하여 새로 만든 컨테이너를 채우는 유사한 패턴을 따릅니다.
XAsyncBlock async{};
PFDataGetFilesRequest requestFiles{};
requestFiles.entity = pEntityKey;
HRESULT hr = PFDataGetFilesAsync(entityHandle, &requestFiles, &async); // Add your own error handling when FAILED(hr) == true
hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
size_t resultSize;
hr = PFDataGetFilesGetResultSize(&async, &resultSize);
std::vector<char> getFilesResultBuffer(resultSize);
PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
hr = PFDataGetFilesGetResult(&async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
정리
게임을 종료할 준비가 되었거나 다른 이유로 PlayFab을 정리해야 하는 경우 열려 있는 모든 핸들을 닫고 PFServicesUninitializeAsync를 호출해야 합니다.
PFEntityCloseHandle(entityHandle);
entityHandle = nullptr;
PFServiceConfigCloseHandle(serviceConfigHandle);
serviceConfigHandle = nullptr;
XAsyncBlock async{};
HRESULT hr = PFServicesUninitializeAsync(&async); // Add your own error handling when FAILED(hr) == true
hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
비동기 API 패턴
PlayFab 서비스 SDK는 GDK에 구현된 비동기 프로그래밍 모델을 따릅니다. 이 프로그래밍 모델에는 XAsync 라이브러리에서 제공하는 작업 및 작업 대기열의 사용이 포함됩니다. 이 모델은 다른 GDK 기능 및 확장(예: Xbox Services API)과 일치합니다. 약간의 복잡성이 발생하지만 비동기 작업에 대한 높은 수준의 제어도 제공합니다.
이 예는 PFDataGetFilesAsync에 대한 비동기 호출을 수행하는 방법을 보여줍니다.
auto async = std::make_unique<XAsyncBlock>();
async->callback = [](XAsyncBlock* async)
{
std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // take ownership of XAsyncBlock
size_t resultSize;
HRESULT hr = PFDataGetFilesGetResultSize(async, &resultSize);
if (SUCCEEDED(hr))
{
std::vector<char> getFilesResultBuffer(resultSize);
PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
PFDataGetFilesGetResult(async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
}
};
PFDataGetFilesRequest requestFiles{};
requestFiles.entity = m_pEntityKey;
HRESULT hr = PFDataGetFilesAsync(m_entityHandle, &requestFiles, async.get());
if (SUCCEEDED(hr))
{
async.release(); // at this point, the callback will be called so release the unique ptr
}
오류 처리
완료된 XAsync 작업은 HTTP 상태 코드를 반환합니다. 오류 상태 코드는 XAsyncGetStatus() 또는 PF*Get() API 중 하나를 호출할 때 HTTP_E_STATUS_NOT_FOUND와 같은 실패 HRESULT로 나타납니다.
서비스에서 반환된 자세한 오류 메시지를 보려면 디버깅에 대한 다음 섹션을 참조하세요. 이러한 자세한 오류 메시지는 개발 중에 PlayFab 서비스가 클라이언트의 요청에 반응하는 방식을 더 잘 이해하는 데 유용할 수 있습니다.
디버깅
결과를 확인하고 PlayFab 서비스 SDK에서 모든 호출을 디버깅하는 가장 쉬운 방법은 디버그 추적을 활성화하는 것입니다. 디버그 추적을 활성화하면 디버거 출력 창에서 결과를 확인하고 결과를 게임 자체 로그에 연결할 수 있습니다.