박상권의 삽질블로그

[안드로이드/Android]Flavors로 같은 소스코드 다른앱 만들기 본문

IT/Android-TIP (한글)

[안드로이드/Android]Flavors로 같은 소스코드 다른앱 만들기

박상권 2017.05.12 19:11


저는 개인앱을 여러개 운영하고 있습니다.

앗! 이 포스팅을 통해 제 개인앱중 몇가지를 소개해 드리겠습니다.



#특가특공대

- 특가항공권 프로모션/이벤트 정보 알림

https://play.google.com/store/apps/details?id=com.gun0912.promotion


        





#이번에내려요

- 목적지 도착 알림(도착지 알림)

https://play.google.com/store/apps/details?id=com.gun0912.Nmap


        



이런 개인앱을 운영하면서 그안에 광고를 넣고 수익을 내고 있습니다.

하지만 이런 광고를 싫어하는 사용자들도 있습니다.

돈주고 살테니 유료앱을 만들어서 제공해달라고 하는 사용자들도 있었습니다.


그래서 저는 무료앱뿐만 아니라 유료앱을 만들기로 하였습니다.

무료앱과 유료앱의 소스코드상에서 차이는 딱 1가지일것입니다.

'광고를 표시하느냐 마느냐'


그냥 아무생각 없이 만들었다면 프로젝트를 복사해서 2개의 프로젝트로 나누고 한군데에서는 광고를 표시하고 나머지 다른데에서는 광고를 표시하지 않게 했을 것입니다.

만약 수정사항이 발생하거나 추가적인 기능이 필요하다면 각각 2개의 프로젝트에 소스코드를 넣어주는 번거롭고 오류를 발생시킬만한 여지가 있는 상황에 놓이게 됩니다.



이럴때 Flavor를 이용한다면 유용합니다.

Flavor는 대부분의 소스코드는 똑같고 일부 값에 의해서 동작을 달리 해야하거나, 앱이름/아이콘을 달리해야하거나 등등의 상황일경우에 유용하게 쓰일 수 있습니다.


이런 경우가 유용하게 쓰일것입니다.


1. 유료앱/무료앱에 따라서 광고를 보여주거나 기타 설정을 다르게 하고 싶은 경우

2. 플레이스토어, 원스토어, 바이두, 텐센트등 배포하는 마켓에 따라서 표시하는 내용이나 값을 다르게 하고 싶은 경우

3. 고객용/관리자용 혹은 고객용/업체용 등으로 버전을 나누어야 하는 경우

4. 기획자가 개발,스테이징,운영 환경에 따른 각각의 앱동작을 확인하고 싶은 경우

5. 국가별/언어별로 앱의 내용을 달리 해서 보여주고 싶은 경우






저는 유료앱과 무료앱에 따라서 광고를 보여주고 안보여주고 앱아이콘과 앱이름을 다르게 표시해주는 샘플앱을 만들어 보겠습니다.




productFlavors 선언 


app의 build.gradle에 아래와 같이 productFlavors 내용을 선언해 줍니다.

android {

productFlavors {
free {
applicationIdSuffix ".free"
versionCode 1
versionName "1.0.0"
}

paid {
applicationIdSuffix ".paid"
versionCode 2
versionName "1.0.1"
}
}


}

applicationIdSuffix를 이용하면 원래의 applicationId 뒤에 각각 free/paid앱의 아이디가 추가로 붙게됩니다.

예를들어 기본 application id가 'com.gun0912'였다면

free는 'com.gun0912.free'가 되고 paid는 'com.gun0912.paid'의 application id가 됩니다.

versionCode, versionName을 각각 설정해서 버전관리를 해주도록 합니다.


이렇게 flavor로 앱을 나누고 나면 BuildVariant에서 2개의 앱이 각각 나누어서 생기는것을 확인해 보실 수 있습니다.

앱을 실행할때 각각의 free/paid로 나누어서 실행할 수 있습니다.









변수 활용하기



무료앱/유료앱에 따라서 광고를 보여주고 보여주지 않기위해서 buildConfigField를 활용합니다.


android {

productFlavors {
free {
...
buildConfigField 'boolean', 'IS_FREE', "true"
}

paid {
...
buildConfigField 'boolean', 'IS_FREE', "false"
}
}


}

위와 같이 선언하면 소스코드에서 아래와 같이 사용할 수 있습니다.


if(BuildConfig.IS_FREE){
// 무료앱
// 광고 보여주기
}else{
// 유료앱
// 광고 보여주지 않기
}

이뿐만 아니라 flavor를 사용하는 목적에 맞게 여러 변수들을 만들고 소스코드상에서 이를 구분해서 활용할 수 있습니다.











앱 이름 달리하기


각각의 앱의 이름을 다르게 정해줄 수도 있습니다.

이럴때 manifestPlaceholders를 이용합니다.


android {

productFlavors {
free {
...

manifestPlaceholders = [ appLabel: "Flavor(Free)" ]
}

paid {
...

manifestPlaceholders = [ appLabel: "Flavor(Paid)" ]

}
}


}

appLabel을 각각 원하는 이름을 정해두고 이를 아래의 Manifest에 변수로 넣어주면 됩니다.



<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="${appLabel}"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>









앱 아이콘 달리하기


각각 앱에 따라서 이름을 다르게 한것처럼 아이콘도 다르게 할 수 있습니다.

Flavor를 사용하느냐 사용하지 않느냐에 따라서 폴더의 구조가 아래와 같이 나뉘게 됩니다.


<Flavor 미사용> <Flavor 사용> ┗━app ┗━app ┗━src ┗━src ┗━main ┣━free ┣━java ┃ ┣━java                 ┗━res         ┃ ┗━res                      ┣━main                  ┃ ┣━java                      ┃ ┗━res                      ┗━paid

                     ┃ ┣━java (노가다...)                       ┃ ┗━res

각각 free, paid의 res폴더에 같은 이름의 아이콘을 넣어주면 앱은 build 환경에 따라서 그에맞는 앱아이콘을 표시해줄것입니다.




이미지 뿐만 아니라 dimens.xml, string.xml 등 각자 원하는 방법에 따라서 이 폴더구조를 활용하면 됩니다.

위에서 살펴보았던 앱의 이름을 달리 하는 방법도 manifestPlaceholders를 사용하지 않고 각각 free, paid폴더에 string.xml에 앱이름을 넣는 방법으로도 가능합니다.


위와같이 앱을 만들어서 각각 설치를 해주면 소스코드는 똑같지만 내용은 다른 2개의 앱이 설치되어 있는것을 확인할 수 있습니다.





백문이불여일견이죠

위의 샘플 예제는 Github에서 다운받아서 테스트 해보실 수 있습니다.

https://github.com/ParkSangGwon/ProductFlavorSample


Github을 들어가셨다면 꼭 Star 눌러주시면 감사하겠습니다!

저에게는 별풍선 주시는 효과가 있어요!





좀더 자세한 내용이 궁금하시다면 구글 공식 문서를 살펴보셔도 좋습니다.

소스코드는 비슷하지만 일부분만 다른 앱을 만들고 싶으시다면 flavor를 활용해서 효율적인 코딩을 하시기 바랍니다.

감사합니다. 


3 Comments
댓글쓰기 폼