안드로이드 마켓 배포를 편하게 해보자 "google publisher api v3"

2021. 1. 24. 23:34Development/[Android] 안드로이드

728x90

안드로이드 앱 개발의 최종단계라고 할 수 있는 구글 플레이 배포.

앱이 1, 2개인 경우는 상관이 크게 없을지 모르나, 관리하고 있는 앱이 10개 이상을 넘어가기 시작하면

사용자 배포 이슈가 있을때마다 일일히 google play consoel 에 접속해서 앱을 배포하는 것이 얼마나 귀찮은 일인지는 현업을 뛰어보면 알 수 있다.

이때 구글에서 제공하는 "google publisher api v3" 를 사용하면 소스 단에서 바로 빌드하여 바로 업로드, 배포까지 논스톱으로 진행할 수 있다.

배포와 관련해서는 fastlane 이라는 스크립트 대체제가 있으나, 자바나 파이썬에 익숙하고

심플하게 관리할 운영툴을 만들고 싶다면 "google publisher api" 가 좋은 방법일 수 있다.

 

우선 공식 샘플 소스(github.com/googlesamples/android-play-publisher-api/tree/master/v3/java)를 살펴보면

다음과 같은 구조를 지니고 있다.

src에 위치한 메인 클래스 파일들

 

나는 방송에서도 블로그에서도 여러번 언급했지만, 소스를 일일히 한줄한줄 파악하려고 하는 것이 아니라 일단 큰 흐름으로 이해하는게 더 도움이 된다는 생각을 가지고 있어서 다음과 같이 정리해보았다.

대충의 흐름은, 

(1) ApplicationConfig 클래스에 마켓 배포를 위한 필수 정보를 셋팅

(2) AndroidPublisher 클래스의 init 메소드를 통해 최초 인증과정을 거친다 (별도 설명)

(3) BasicUploadApk 클래스로 배포.

과 같다.

 

(2)번의 최초 인증과정이라함은 2가지 방법이 존재하는데,

내가 이 API를 사용하겠다는 인증을 받는 것인데, 

하나는 client (업로드하는 컴퓨터) 와 관련된 설정파일 json을 로컬에 저장해놓고 인증받거나

다른 하나는 최초 업로드 실행시 구글 플레이 마켓에 접속가능한 실제 구글 아이디로 로그인(브라우저가 자동으로 뜨고 로그인하라고 한다)하는 방법이다. 

사용해본바, 후자의 경우가 훨씬 편하다. 

차이점이라면 전자의 경우 셋팅할 것이 좀 있는데 이곳에서는 언급하지 않겠다... (스샷따기 귀찮.....)

 

일단 샘플소스만으로는 실제 테스트를 해보기가 어렵기때문에,

아래와 같은 흐름으로 고쳐본다.

 

(1) 마켓에 배포할 앱 정보를 담는 ApplicationConfig 클래스는 기존 디폴트 생성자외에 생성자를 하나 더 만든다.

//ApplicationConfig 클래스
//기존
private ApplicationConfig() {
        // no instance
}

//생성자를 하나 더 만든다
public ApplicationConfig(String appName, String pkgName, String apkPath) {
        // no instance
        this.APPLICATION_NAME = appName;
        this.PACKAGE_NAME = pkgName;
        this.APK_FILE_PATH = apkPath;
}

 위와 같이 일단 최초 설정할 값들을 받는 생성자를 만들어 놓고..

(2) 최초 마켓 인증과정은 자동으로 진행되므로 크게 신경쓸것은 없고..

(3) 업로드 로직을 구성한다.

//기존 BasicUploadApk 클래스에는 업로드하는 로직이 main 메소드에 있기때문에 아래와 같이 별도 업로드 메소드로 옮겨 만들어 준다.
public TRACK track; 	   			//어느 트랙으로 배포할지
public LANGUAGE updateCommentLang;  //코멘트 부분의 언어
public String updateComment;    	//업데이트 코멘트
    
public enum TRACK {
        alpha {
            @Override
            public String toString() {
                return "alpha";
            }
        },
        beta {
            @Override
            public String toString() {
                return "beta";
            }
        },
        production {
            @Override
            public String toString() {
                return "production";
            }
        }
}
    
public BasicUploadApk(TRACK track, LANGUAGE updateCommentLang, String updateComment) {
        this.track = track;
        this.updateCommentLang = updateCommentLang;
        this.updateComment = updateComment;
}

public boolean processUpdate() {
    	//실제 마켓에 업로드 처리하는 로직
        //앞 소스는 동일하게
        
        //실제 업로드 로직부분만 수정한다.
        List<Long> apkVersionCodes = new ArrayList<>();
            apkVersionCodes.add(Long.valueOf(apk.getVersionCode()));
            Update updateTrackRequest = edits
                    .tracks()
                    .update(ApplicationConfig.PACKAGE_NAME,
                            editId,
                            this.track.toString(),
                            new Track().setReleases(
                                    Collections.singletonList(
                                            new TrackRelease()
                                                    .setName(String.valueOf(apk.getVersionCode()))
                                                    .setVersionCodes(apkVersionCodes)
                                                    .setStatus("completed")
                                                    .setReleaseNotes(Collections.singletonList(
                                                            new LocalizedText()
                                                                    .setLanguage(this.updateCommentLang.toString())
                                                                    .setText(this.updateComment)
                                                            )
                                                    )
                                    )
                            )
                    );
                    
        //뒷소스도 동일하게
}
    
    

위와 같이 수정하고

다른 곳에서 아래와 같이 호출하면 샘플 소스를 살짝만 손보고 바로 현업에 사용이 가능하다.

//config init
ApplicationConfig config = new ApplicationConfig(appName, pkgName, apkPath);

//upload
BasicUploadApk basicUploadApk = new BasicUploadApk(track, updateCommentLang, updateComment);
basicUploadApk.processUpdate();

//*. config를 아예 BasicUploadApk 클래스에 내제화 시켜버릴수도(?)

 

쉬운 예제와 쉬운 문서로 사용자들을 도와주는 샘플소스와 레퍼런스는 역시 최고의 선생님이다..

 

어쩌면 내 블로그도 그럴지 모르지만, (그리고 반향을 일으킬 내용일수도 있지만)

이런 샘플소스와 레퍼런스 문서는 어려운(?) 영어지만 그 어떤 거창한 IT 회사들의 알수없는 용어들로 버무려진 개발자들의 블로그보다 쉽게 따라할 수 있게, 이해할 수 있게 해준다.

 

오늘도,

Mission Accomplished!

 

 

 

 

728x90