본문 바로가기
PROGRAMING📚/Unity📑

[유니티Unity]유니티에서 인앱 업데이트 지원 하기

별찌루 2023. 1. 27.
728x90
반응형

유니티에서 인앱 업데이트 지원 하기

 

구글 콘솔에 새로운 버전을 업데이트했을 때,

인앱 업데이트 기능을 넣어주지 않으면 사용자가 직접 앱을 업데이트시켜주어야 한다.

 

하지만 중요한 기능의 업데이트 일 경우,

업데이트를 해주어야하기 때문에 이러한 경우에 앱 안에서

업데이트를 진행할 것 인지 아닌지에 대해서 확인해주어야 하기 때문에

다음과 같이 안드로이드에서 인앱 업데이트를 지원해주고 있다.

 

 

https://developer.android.com/guide/playcore/in-app-updates/unity?hl=ko 

 

인앱 업데이트 지원(Unity)  |  Android 개발자  |  Android Developers

인앱 업데이트 지원(Unity) 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 가이드에서는 Unity를 사용하여 앱에서 인앱 업데이트를 지원하는 방법을 설명합

developer.android.com

 

인앱 업데이트를 사용하기 위해서 

아래의 사이트에서 Play 인앱 업데이트 패키지를 다운로드하아야 한다.

 

https://developers.google.com/unity/packages?hl=ko#play_in-app_update

 

패키지를 프로젝트 안에 다운로드하면

GooglePlayPlugins 안에  appupdate 패키지가 생성된 것을 확인할 수 있다.

 

이제 다운로드한 패키지를 이용해서 업데이트 기능을 만들어 주어야 한다. 

 

 

인앱 업데이트를 관리하기 위해서는

코루틴(IEnumerator)을 사용해서 업데이트 할 내용이 있는지 확인해준다. 해준다.

 

클래스를 인스턴스화해주어 Play API 간 통신을 처리할 수 있도록 해주어야 한다.

 

//AppUpdateManager : 앱 내에 업데이트를 요청하고 시작하는 작업
AppUpdateManager appUpdateManager = new AppUpdateManager();
PlayAsyncOperation< AppUpdateInfo, AppUpdateErrorCode > GetAppUpdateInfo()

 

PlayAsyncOperation<AppUpdateInfo, AppUpdateErrorCode> 는  AppUpdateManager 의 기능중 하나로

인앱 업데이트 정보를 얻기 위해서 네트워크를 호출 하는 기능이다.

 

PlayAsyncOperation< AppUpdateInfo, AppUpdateErrorCode > GetAppUpdateInfo()를 바로 사용할 수 없어서 

다음과 같이 선언해 주고 AppUpdateManager 클래스에서 GetAppUpdateInfo() 기능을 가져와야 한다.

 

PlayAsyncOperation<AppUpdateInfo, AppUpdateErrorCode> appUpdateInfoOperation;
appUpdateInfoOperation = appUpdateManager.GetAppUpdateInfo();

//비동기 작업이 완료될 때까지 기다립니다.
yield return appUpdateInfoOperation;

https://developer.android.com/reference/unity/class/Google/Play/AppUpdate/AppUpdateManager

 

Google.Play.AppUpdate.AppUpdateManager Class Reference  |  Android Developers

Stay organized with collections Save and categorize content based on your preferences. Google.Play.AppUpdate.AppUpdateManager Manages operations for requesting and launching an in-app update flow. Summary Constructors and Destructors AppUpdateManager() Con

developer.android.com

 

 

업데이트 정보를 가져오기 위해서는 StartUpdate 전에 호출해야 한다.

(즉, 업데이트를 시작하기 전에 GetAppUpdateInfo를 사용해서

AppUpdateInfo(앱 업데이트 가용성, 설치 진행률 정보)를 가져와야 함)

 

AppUpdateManager.GetAppUpdateInfo() 안에는 다음과 같은 정보가 들어가 있다.


 작업이 오류 없이 완료되었는지 여부

appUpdateInfoOperation.IsSuccessful

 

작업이 완료되었는지 여부

appUpdateInfoOperation.IsDone


작업이 오류 없이 완료되었을 경우, 

 

     AppUpdateInfo

UpdateAvailability, UpdatePriority, IsUpdateTypeAllowed() 등을 사용해서

사용자에게 요청할지  여부를 결정하여 앱 내 업데이트를 시작합니다.

 

더보기

UpdateAvailability

 

(특성)

1. Unknown

업데이트 가용성을 알수 없음

2. UpdateAvailable

업데이트를 사용할 수 있음

3. UpdateNotAvailable

업데이트가 없음

4. DeveloperTriggeredUpdateInProgress

개발자에 의해 업데이트가 작동되었음

 

UpdatePriority

개발자가 GooglePlay Developer API의 edits.track의 "inAppUpdatePriority" 필드를 사용하여

정의한 대로 이 업데이트의 우선순위를 반환

 

IsUpdateTypeAllowed(AppUpdateOptions appUpdateOptions)

지정된 옵션의 업데이트가 허용되면 true를 반환하고 그렇지 않으면 false를 반환

 

 

GetAppUpdateInfo()에서 불러온 인앱업데이트 정보와  비교해서 작업을 처리해 주어야한다.

 

업데이트가 가능한 경우(UpdateAvailable = 2)

 

업데이트를 처리 하는 방법으로

유연한 업데이트 처리 방식과 즉시 업데이트 방식 두가지가 있다.

 

 *AppUpdateOptions : AppUpdateType을 포함하여 앱 내 업데이트를 구성하는 데 사용되는 옵션

AppUpdateOptions.FlexibleAppUpdateOptions() // 유연한 업데이트 처리 AppUpdateType =0

 AppUpdateOptions.ImmediateAppUpdateOptions() //즉시 업데이트 처리 AppUpdateType =1

 

유연한 업데이트 방식은 사용자에게 업데이트를 할 것인지에 대해 물어보고

업데이트 할 것인지 아닌지를 선택 여부를 제공한다.

즉시 업데이트 방식은 유연한 방식과는 반대로 업데이트를 강제로 시킨다고 할 수 있다.

 

AppUpdateOptions(업데이트 처리)를 해주어야 AppUpdateManager.StartUpdate() - 업데이트를 할 수 있다. 

 


AppUpdateManager.StartUpdate 사용하는 방법

 

AppUpdateRequest StartUpdate
(
	//appUpdateInfoOperation.GetResult()의 결과를 가져옴
	AppUpdateInfo appUpdateInfo, 
	//업데이트 처리 방식을 가져옴
	AppUpdateOptions appUpdateOptions 
)

 


AppUpdateRequest

 

앱 업데이트의 진행률 나타내기

Google.Play.AppUpdate.AppUpdateRequest(앱업데이트요구)

 

업데이트 중인 앱을 모니터링 하는데 사용한다.

 

Google.Play.AppUpdate.AppUpdateRequest (앱업데이트요구)

IsDone : 업데이트가 완료되면 True를 반환하고 아니면 False를 반환
BytesDownloaded : 이미 다운로드 된 총 바이트 수를 반환
DownloadProgress : 유연한 업데이트 흐름의 전체 다운로드 진행률을 0~1 의 값으로 반환
Error : 업데이트를 성공적으로 완료하지 못했을 경우, 오류를 반환
Status : AppUpdateStatus(업데이트 상태)를 반환 
TotalBytesToDownload : 업데이트를 위해 다운로드 할 총 바이트 수를 반환
keepWaiting : 요청이 코루틴에서 제출될 수 있도록 속성을 구현

 

Status : AppUpdateStatus(업데이트 상태)를 반환 

 

 

Canceled : 업데이트 취소
Downloaded : 업데이트 다운로드 완료 
Downloading : 업데이트 다운로드 진행중
Failed : 업데이트 실패
Installed : 업데이트 성공적으로 설치됨
Installing : 업데이트를 설치하는 중
Pending : 업데이트 다운로드가 보류중으로 곧 처리될 예정
Unknown : 업데이트 상태를 알 수 없음

 

  

appUpdateManager.CompleteUpdate()

 

StartUpdate를 통해 시작된 유연한 입앱 업데이트 흐름을 완료하도록 비동기적으로 요청함,

AppUpdateRequest가 완료되고 호출 해야함


 

 

Google.Play.AppUpdate 클래스 


AppUpdateInfo : 앱의 업데이트 가용성 및 설치 진행률에 대한 정보
AppUpdateManager : 앱 내에 업데이트를 요청하고 시작하는 작업
AppUpdateOptions : AppUpdateType을 포함하여 앱 내 업데이트를 구성하는 데 사용되는 옵션입니다.

AppUpdateRequest : 진행 중인 앱 내 업데이트를 모니터링하는 데 사용되는 사용자 지정 수율 명령입니다.(?)

 



<< 전체 코드 정리 >>

//AppUpdateManager 인앱 업데이트 지원 
using Google.Play.AppUpdate;
using Google.Play.Common;



/// <summary>
/// https://developer.android.com/reference/unity/class/Google/Play/AppUpdate/AppUpdateInfo#clientversionstalenessdays
/// https://developer.android.com/reference/unity/namespace/Google/Play/AppUpdate
/// </summary>
public class CheckAppUpdate : MonoBehaviour
{
    public TMP_Text updateStatusLog;
    public TMP_Text updateStatus_test1;
    public TMP_Text updateStatus_test2;
    AppUpdateManager appUpdateManager = null;
    //유니티 플러그 인앱과 Play API 간 통신을 처리하는 AppUpdateManager 클래스

    //앱 업데이트 작업

    //
    private void Awake()
    {
        //업데이트 하고 얼마나 지났는지 경과 일수 확인 하는 방법
        // var stalenessDays = appUpdateInfoOperation.GetResult();
        StartCoroutine(CheckForUpdate());
    }
    /// <summary>
    /// Google.Play.AppUpdate 클래스 
    /// AppUpdateInfo : 앱의 업데이트 가용성 및 설치 진행률에 대한 정보
    /// AppUpdateManager : 앱 내에 업데이트를 요청하고 시작하는 작업
    /// AppUpdateOptions : AppUpdateType을 포함하여 앱 내 업데이트를 구성하는 데 사용되는 옵션입니다.
    /// AppUpdateRequest : 진행 중인 앱 내 업데이트를 모니터링하는 데 사용되는 사용자 지정 수율 명령입니다.(?)
    /// </summary>
    /// <returns></returns>
    //업데이트 사용 가능 여부를 확인 
    IEnumerator CheckForUpdate()
    {
        appUpdateManager = new AppUpdateManager();
        PlayAsyncOperation<AppUpdateInfo, AppUpdateErrorCode> appUpdateInfoOperation;
        appUpdateInfoOperation = appUpdateManager.GetAppUpdateInfo();
        // Wait until the asynchronous operation completes.
        //비동기 작업이 완료될 때까지 기다립니다.
        yield return appUpdateInfoOperation;

        // var appUpdateOptions = AppUpdateOptions.FlexibleAppUpdateOptions();

        if (appUpdateInfoOperation.IsSuccessful)
        {
            // Check AppUpdateInfo's UpdateAvailability, UpdatePriority,
            // IsUpdateTypeAllowed(), etc. and decide whether to ask the user
            // to start an in-app update.

            /*AppUpdateInfo의 UpdateAvailability, UpdatePriority,
            IsUpdateTypeAllowed() 등 및 사용자에게 요청할지 여부를 결정
            앱 내 업데이트를 시작합니다.*/

            var appUpdateInfoResult = appUpdateInfoOperation.GetResult();
            //  AppUpdateManager.StartUpdate() 업데이트를 요청 
            //  업데이트를 요청하기 전에 최신 AppUpdataeInfo가 있는지 확인해야함
            //  UpdateAvailability ,앱 내 업데이트에 대한 가용성 정보입니다.
            if (appUpdateInfoResult.UpdateAvailability == UpdateAvailability.UpdateAvailable)
            {
                Debug.Log("start updateAble");
                //업데이트 사용 가능
                /// AppUpdateOptions : AppUpdateType을 포함하여 앱 내 업데이트를 구성하는 데 사용되는 옵션입니다.
                var appUpdateOptions = AppUpdateOptions.FlexibleAppUpdateOptions(); //유연한 업데이트 처리 AppUpdateType =0
                //var appUpdateOptions = AppUpdateOptions.ImmediateAppUpdateOptions(); //즉시 업데이트 처리 AppUpdateType =1

                //지정된 업데이트 유형에 대해 앱 내 업데이트 시작.
             
                var startUpdateRequest = appUpdateManager.StartUpdate(
                    //appUpdateInfoOperation.GetResult()의 결과를 가져옴
                    appUpdateInfoResult,
                    //업데이트 처리 방식을 가져옴
                    appUpdateOptions);
                updateStatus_test1.text = startUpdateRequest.IsDone.ToString(); 
                //startUpdateRequest.IsDone은 업데이트가 완료가 되면 True, 아닐 경우 Fales
                while (!startUpdateRequest.IsDone)
                {
                    Debug.Log("startUpdateRequest.IsDone");
                    updateStatus_test1.text = startUpdateRequest.IsDone.ToString();
                   
                    if (startUpdateRequest.Status == AppUpdateStatus.Pending)
                    { 
                        //업데이트 다운로드가 보류중 곧 처리 될 예정
                        // downloadProgressbar.gameObject.SetActive(true);
                    }
                    else if (startUpdateRequest.Status == AppUpdateStatus.Downloading)
                    {
                        //업데이트 다운로드가 진행 중 일 경우, 
                        Debug.Log(" AppUpdateStatus.Downloading");
                        updateStatusLog.text = $"Downloading ... {Mathf.Floor(startUpdateRequest.DownloadProgress * 100) }%";
                        //downloadProgressbar.value = startUpdateRequest.DownloadProgress;
                    }
                    else if (startUpdateRequest.Status == AppUpdateStatus.Downloaded)
                    {
                        //업데이트가 완전히 끝난 경우,
                        Debug.Log("AppUpdateStatus.Downloaded");
                        //downloadProgressbar.gameObject.SetActive(false);
                    }
                    yield return null;
                }
                //StartUpdate를 통해 시작된 유연한 입앱 업데이트 흐름을 완료하도록 비동기적으로 요청함, 
                //AppUpdateRequest가 완료되고 호출 해야함
                var result = appUpdateManager.CompleteUpdate();

                //업데이트가 완전히 끝난게 아니면
                while (!result.IsDone)
                {
                    yield return new WaitForEndOfFrame();
                    Debug.Log("CompleteUpdate.Status 2: " + startUpdateRequest.Status);
                    updateStatusLog.text = $"{startUpdateRequest.Status}.";
                }

                updateStatusLog.text = $"{startUpdateRequest.Status}";
                // 앱 내 업데이트 api 상태
                //https://developer.android.com/reference/unity/namespace/Google/Play/AppUpdate#appupdatestatus
                //0 : Unknown 1:Pending 2:Downloading 3:Downloaded 4:Installing 5:Installed 6:Failed 7:Canceled
                yield return (int)startUpdateRequest.Status; 
            }
            else if (appUpdateInfoResult.UpdateAvailability == UpdateAvailability.DeveloperTriggeredUpdateInProgress)
            {
                //개발자 트리거 업데이트 진행 중
                updateStatusLog.text = "Update In Progress..";
                //  downloadProgressbar.gameObject.SetActive(true);

                var appUpdateOptions = AppUpdateOptions.ImmediateAppUpdateOptions(); //즉시 업데이트 처리 
                var startUpdateRequest = appUpdateManager.StartUpdate(appUpdateInfoResult, appUpdateOptions);
                //업데이트가 완료 되지 않은 상황이면, 
                while (!startUpdateRequest.IsDone)
                {
                    yield return new WaitForEndOfFrame();
                    Debug.Log(appUpdateInfoResult.ToString());

                    //다운로드 중 일 때,
                    if (startUpdateRequest.Status == AppUpdateStatus.Downloading)
                    {
                        updateStatusLog.text = $"Downloading ... {Mathf.Floor(startUpdateRequest.DownloadProgress * 100) }%";
                        //    downloadProgressbar.value = startUpdateRequest.DownloadProgress;
                    }
                    //다운로드가 끝났으면
                    else if (startUpdateRequest.Status == AppUpdateStatus.Downloaded)
                    {
                        //  downloadProgressbar.gameObject.SetActive(false);
                    }
                }
                var result = appUpdateManager.CompleteUpdate();
                while (!result.IsDone)
                {
                    yield return new WaitForEndOfFrame();
                    updateStatusLog.text = $"{startUpdateRequest.Status}";
                }
                updateStatusLog.text = $"{startUpdateRequest.Status}";
                // 앱 내 업데이트 api 상태
                //https://developer.android.com/reference/unity/namespace/Google/Play/AppUpdate#appupdatestatus
                //0 : Unknown 1:Pending 2:Downloading 3:Downloaded 4:Installing 5:Installed 6:Failed 7:Canceled
                yield return (int)startUpdateRequest.Status;
            } 
            //업데이트를 사용할 수 없음
            else if (appUpdateInfoResult.UpdateAvailability == UpdateAvailability.UpdateNotAvailable)
            {
                updateStatus_test2.text = "업데이트 사용 불가";
                yield return (int)UpdateAvailability.UpdateNotAvailable;  // 1
            }
            else
            {
                updateStatus_test2.text = "Else";
                yield return (int)UpdateAvailability.Unknown; // 0
            }


            //   var startUpdateRequest = appUpdateManager.StartUpdate(
            //       // PlayAsync Operation에서 반환한 결과입니다.결과 가져오기().
            //       appUpdateInfoResult,
            //       //요청된 앱 내 업데이트 및 해당 매개 변수를 정의하는 앱 업데이트 옵션이 생성되었습니다.
            //       appUpdateOptions);

        }
        else
        {
            // Log appUpdateInfoOperation.Error.
            //appUpdateInfoOperation을 기록합니다.오류.
        }
    }
    }
728x90
반응형

댓글