Android에서 Ant(build.xml)로 마켓 별 바이너리 빌드하기..

안드로이드 마켓은 애플 앱스토어와 다르게, 통신사나 회사에서 마켓을 만들어서 서비스 할 수 있다. 그래서 여러 안드로이드 마켓을 확인할 수 있다. 안드로이드 앱을
개발하면, Play 마켓 과 더불어 아마존 이나 티스토어 등의 여러 마켓에 런칭하는 경우가 있다. 개별 앱 마켓에 앱을 런칭하는 경우, 개별 마켓은 고유한 정책을 가지고 있고, 정책에 위배되면, 위배되는 내용을 수정해서 다시 요청(Play 마켓을 제외한 다른 마켓들은 거의 리뷰를 한다)해야 한다.

개별 마켓이 가지고 있는 정책중에 하나가, 앱에 대한 설명이나 앱의 주소가 적인 URL(http://play.google.com과 같은 주소는 다른 마켓에서 반려 사유가 된다)이 문제가 되는 경우가 있다. 그리고 개별 마켓에서 설치한 앱은 마켓 별로 다른 메세지를 보여줄 필요도 있다.

그래서, 앤트(Ant, build.xml)를 사용해서 마켓별로 앱을 패키징 하는 방법을 살펴보자.

1. 기본적인 구조

기본적인 패키지의 구조는 좌측과 같습니다..

2.3 버전부터 지원할 수 있는 형태로 프로젝트를 생성했습니다.

좌측의 패키지 구조를 살펴보면…

\libs-ext : 마켓의 분리를 위해서 필요한 Market.java를 폴더별로 가지고 있습니다.

build.properties : 릴리즈를 하기 위한 인증서의 위치와 정보를 저장하는 파일..

build.xml : 빌드 스크립트 파일..

local.properties : 로컬의 SDK 위치를 가리치는 파일..

project.properties : target project의 버전정보를 가지고 있는 파일..

 

참고로, 검은색으로 칠해버린 넘은 인증서 파일입니다..

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2. 코드 보기..

 

 

 

 

 

 

 

2.1 MainActivity.java

– 화면에 마켓의 정보를 보여주는 클래스..

package net.sjava.buildtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

import net.sjava.buildtest.util.Constants;

public class MainActivity extends Activity {
	private TextView tv;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        tv = (TextView)findViewById(R.id.main_textview);
        tv.setText(Constants.getMarketString(MainActivity.this));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

2.2 Constants.java

– 마켓에 대한 정보를 넘겨주는 클래스..

package net.sjava.buildtest.util;

import android.content.Context;
import net.sjava.buildtest.R;
import net.sjava.buildtest.util.config.Debug;
import net.sjava.buildtest.util.config.Market;

public class Constants {
	public static final boolean DEBUG = Debug.DEBUG;
	public static final int MARKET = Market.MARKET;
	
	public static String getMarketString(Context c) {
		if(c == null)
			return "";
		
		if(MARKET == 0)
			return c.getString(R.string.mk_play);
					
		if(MARKET == 1)
			return c.getString(R.string.mk_amazon);
		
		if(MARKET == 2)
			return c.getString(R.string.mk_tstore);
		
		return "";
	}
}

 

2. 마켓의 정보를 구분하기..

마켓의 정보는 위의 폴더에서 자신의 상수값을 가지고 있게 된다..

따라서, 첨부한 소스를 확인해 보면, mk-play 폴더의 Market.java는 상수값으로 1을 가지고 있다..

 

3. 빌드 스크립트..

– 빌드 스크립트인 build.xml은 구글의 프레임웍이 빌드를 하기 위한 스크립트를 제공하기 때문에 매우 간단하게 작성을 할 수 있다.. 떙큐.. ^^, 아래의 스크립트는 dev/rc/live 같은 개발/라이브의 테스트/라이브 별도 바이너리를 릴리즈 하는 스크립트는 포함하지 않지만, 이것도 쉽게 추가할 수 있다.. 또한, 포함되어 있지 않지만, obfuscate를 위해서  proguard가 포함되어 있어, obfucate를 쉽게 지원한다.

 

3.1 build.properties

#
# Set the keystore properties for signing the application.
# 맞게 수정하시면 됩니다.. ^^
key.store=./libs-ext/xxxx
key.alias=xxxx

key.store.password=xxxx
key.alias.password=xxxx

3.2 local.properties

# location of the SDK. This is only used by Ant
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=C:\\Program Files\\android\\android-sdk

 

3.3 project.properties

# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.
target=android-16

 

3.4 build.xml

– 아래의 빌드 스크립트의 buildtest-release-all 타켓을 실행해서, 마켓별 바이너리를 뽑아낼 수 있다.

 

<?xml version=”1.0″ encoding=”UTF-8″?>
<project name=”BuildTest” default=”help”>
<property file=”local.properties”/>
<property file=”build.properties” />
<property file=”project.properties” />

<!–property name=”config-target-dir-path” value=”net/sjava/buildtest/util/config” /–>
<property name=”market-target-dir-path” value=”net/sjava/buildtest/util/config” />

<property name=”project.name” value=”BuildTest”/>
<property name=”dist.dir” value=”./dist/” />
<property name=”release.file” value=”./bin/BuildTest-release.apk” />
<property name=”dist.backup” value=”c:/dev/dist” />

<path id=”android.antlibs”>
<fileset dir=”${sdk.dir}/tools/lib/” includes=”*.jar” />
</path>

    <!– 안드로이드 SDK가 제공하는 build.xml을 사용하기 위해서 import 한다.. –>
    <import file=”${sdk.dir}/tools/ant/build.xml”/>

    <!–AndroidManifest에서 xpath를 이용해서 선언된 versionName 값을 가져온다. –>
    <xpath input=”AndroidManifest.xml” expression=”/manifest/@android:versionName” output=”versionName” default=”1.0.0″/>

<tstamp>
<format property=”touch.time” pattern=”yyyyMMdd_HHmm” />
</tstamp>

<target name=”switch-market”>
<echo>Market Configuration file: ${market.filename}</echo>
<property name=”market-target-path” value=”${source.dir}/${market-target-dir-path}” />
<copy file=”${market.filename}” todir=”${market-target-path}” overwrite=”true” encoding=”utf-8″ />
</target>

<target name=”buildtest-backup”>
<copy todir=”${dist.backup}/${project.name}/${versionName}_${touch.time}”>
<fileset dir=”./dist”/>
</copy>
</target>

<target name=”buildtest-release-mk-play”>
<echo>Selected release configuration</echo>
<antcall target=”clean” />

<antcall target=”switch-market”>
<param name=”market.filename” value=”libs-ext/mk-play/Market.java” />
</antcall>

<property name=”proguard.enabled” value=”false”/>
<antcall target=”release” />
<copy file=”${release.file}” tofile=”${dist.dir}/${project.name}_live_play_${versionName}_${touch.time}.apk”/>
</target>

<target name=”buildtest-release-mk-amazon”>
<echo>Selected release configuration</echo>
<antcall target=”clean” />

<antcall target=”switch-market”>
<param name=”market.filename” value=”libs-ext/mk-amazon/Market.java” />
</antcall>

<property name=”proguard.enabled” value=”false”/>
<antcall target=”release” />
<copy file=”${release.file}” tofile=”${dist.dir}/${project.name}_live_amazon_${versionName}_${touch.time}.apk”/>
</target>

<target name=”buildtest-release-mk-tstore”>
<echo>Selected release configuration</echo>
<antcall target=”clean” />

<antcall target=”switch-market”>
<param name=”market.filename” value=”libs-ext/mk-tstore/Market.java” />
</antcall>

<property name=”proguard.enabled” value=”false”/>
<antcall target=”release” />
<copy file=”${release.file}” tofile=”${dist.dir}/${project.name}_live_tstore_${versionName}_${touch.time}.apk”/>
</target>

<target name=”buildtest-release-all”>
<echo>Start distribute binaries all of the market</echo>
<antcall target=”buildtest-release-mk-play” />
<antcall target=”buildtest-release-mk-amazon” />
<antcall target=”buildtest-release-mk-tstore” />
</target>

</project>

 

4. 결과

– 위의 코드를 통해서 마켓별로 필요한 URL이나, 리소스를 구분해서 보여줄 수 가 있겠습니다.. 아래의 화면은 만들어진 바이너리가 마켓별로 구분된 메세지를 보여주는지 테스트한 화면입니다..

 

아래의 명령을 통해서 각 바이너리를 에뮬레이터에 설치해서 테스트 하시면 됩니다.

> adb install BuildTest_live_amazon_1.0_20120918_2132.apk

> adb install BuildTest_live_tstore_1.0_20120918_2132.apk

 

 

5. 소스

cfile27.uf.1534F3375059F12A030C14.zip

 

 

 

Android에서 Ant(build.xml)로 마켓 별 바이너리 빌드하기..”에 대한 3개의 생각

  1. Minki

    안녕하세요, ant build 테스트 중인데요
    ant build를 한번 하고 나서 소스파일이 변경되어 rebuild 할 경우에 변경된 소스파일이 적용이 안되는데 왜 그런걸까요?
    Ant build 시 clean-build순으로 하였습니다.
    혹시 아신다면 답변부탁드릴께요 ㅠㅠ 감사합니다.

    응답
    1. mcsong

      안녕하세요..
      아래의 antcall이 실제로 프로젝트의 /bin과 연관 라이브러리의 /bin폴더를 전체적으로 삭제시켜 주기 때문에.. 캐시가 날라가게 되어 있습니다.

      혹시, clean을 한 번만 하시고, 빌드를 여러번 돌리신게 아니신지? 이런 경우에는 클래스를 바꿔서 빌드를 돌려도 안 바뀌는 경우가 발생합니다..

      그래서, 위의 코드가 마켓별로 빌드하는 코드에 일일이.. 이 들어가 있는 이유입니다..

      도움이 되셨으면 좋겠네요.. ^^

      응답

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.