빌드 버전에 따라 앱 이름이 다르나요?


95

2 개의 빌드 플레이버, 예를 들어 flavor1flavor2가 있습니다.

내 애플리케이션의 이름을 " AppFlavor1 "( flavor1 용으로 빌드 할 때)과 " AppFlavor2 "( flavor2 용으로 빌드 할 때)로 지정하고 싶습니다.

바꾸고 싶은 활동의 제목이 아닙니다. 휴대폰 메뉴와 다른 곳에 표시되는 앱 이름을 변경하고 싶습니다.

에서 build.gradle나는 앱이 아닌 레이블 것, 내 맛에 대한 다양한 매개 변수를 설정할 수 있지만. 또한 일부 변수를 기반으로 프로그래밍 방식으로 앱 레이블을 변경할 수 없습니다.

그렇다면 사람들은 이것을 어떻게 처리합니까?

답변:


26

스크립트로 기본 strings.xml을 변경하고 소스 제어를 망칠 위험이있는 대신 Android Gradle 빌드의 표준 병합 동작에 의존하지 않는 이유는 무엇입니까?

build.gradle포함

sourceSets {
    main {
        manifest.srcFile 'AndroidManifest.xml'
        java.srcDirs = ['src']
        resources.srcDirs = ['src']
        aidl.srcDirs = ['src']
        renderscript.srcDirs = ['src']
        res.srcDirs = ['res']
        assets.srcDirs = ['assets']
    }

    release {
        res.srcDir 'variants/release/res'
    }

    debug {
        res.srcDir 'variants/debug/res'
    }
}

그래서 지금은 내 정의 할 수 있습니다 app_name에서 문자열을 variants/[release|debug]/res/strings.xml. 그리고 내가 바꾸고 싶은 다른 것!


편집 됨 : res.srcDir을 사용하여 배열을 완전히 재정의하는 대신 배열에 추가하십시오.
Pierre-Luc Paour 2013

예, 나도 지금까지 알아 냈습니다. 감사합니다
Alexander Kulyakhtin 2013

1
sourceSets블록을 어디에 추가해야 합니까? android{...}블록 아래 입니까?
Abel Callejo

@AbelMelquiadesCallejo는 android실제로 블록 내부에 있습니다.
Pierre-Luc Paour

263

제거 app_name에서 strings.xml(중복 자원의 불평 다른 Gradle을). 그런 다음 다음과 같이 빌드 파일을 수정합니다.

productFlavors {
    flavor1{
        resValue "string", "app_name", "AppNameFlavor1"
    }

    flavor2{
        resValue "string", "app_name", "AppNameFlavor2"
    }
   } 

또한 매니페스트의 속성에 @string/app_name값이 할당되어 있는지 확인하십시오 android:label.

<application
        ...
        android:label="@string/app_name"
        ...

이것은 strings.xml다른 빌드 세트에서 새로 작성하거나 사용자 정의 스크립트를 작성하는 것보다 덜 방해가 됩니다.


9
이것은 매력처럼 작동하지만 질문 : 이와 같은 문자열 리소스를 추가 할 때 다른 로케일에 대해 현지화 된 문자열을 어떻게 추가합니까?
AndroidMechanic-Viral Patel

이것에 대한 질문을 여기에 게시했습니다 : stackoverflow.com/questions/36105494/… 제발 좀 봐주 시겠어요?
AndroidMechanic-Viral Patel

3
여러 맛 차원을 사용하는 것은 어떻습니까? 각 맛 / 맛 조합에 대해 어떻게 다른 이름을 지정할 수 있습니까?
Zocket

1
모든 것이 정상이지만 런처 아이콘 아래에 표시되는 앱 이름이 gradle 제품 버전에 의해 설정된대로 변경되지 않습니다. strings.xml에서 "app_name"을 제거하고 제품 맛을 설정했습니다. Android의 App Info 페이지에서 앱 이름이 표시되면 제품 버전별로 설정된 앱 이름이 표시되지만 런처 아이콘 아래에는 이전 앱 이름이 표시됩니다.
iamcrypticcoder

2
@ mahbub.kuet @string/app_name런처 activity라벨에 사용 하고 있습니까? 것을 명심 label메인 실행에서이 activity받는 환경에서 사용되는 application label응용 프로그램의 표시 이름.
user650881 jul.

13

다른 버전에서 앱 이름의 현지화를 유지하려는 경우 다음과 같이 수행 할 수 있습니다.

1) 지정 android:label<application>사용할 AndroidManifest.xml다음과 같다 :

<application
    ...
    android:label="${appLabel}"
    ...
>

2) appLabel앱 수준에서 기본값을 지정하십시오 build.gradle.

manifestPlaceholders = [appLabel:"@string/defaultName"]

3) 다음과 같이 제품 맛의 값을 재정의합니다.

productFlavors {
    AppFlavor1 {
        manifestPlaceholders = [appLabel:"@string/flavor1"]
    }
    AppFlavor2 {
        manifestPlaceholders = [appLabel:"@string/flavor2"]
    }

}

4) 각 문자열 (defaultName, flavor1, flavor2)에 대한 문자열 리소스를 strings.xml. 이를 통해 현지화 할 수 있습니다.


2 단계는 'android'수준이 아닌 build.gradle의 'defaultConfig'수준에 있어야합니다. 그렇지 않으면 manifestPlaceholders 이름과 관련된 알 수없는 속성 오류가 발생합니다.
Brendon Whateley

8

각 버전에 문자열 리소스 파일을 추가 한 다음 해당 리소스 파일을 사용하여 앱 이름을 변경할 수 있습니다. 예를 들어 내 앱 중 하나에 무료 및 유료 버전이 있습니다. "Lite"및 "Pro"의 이름을 변경하기 위해 meta_data.xml파일을 만들고 app_name해당 XML 에 내 값을 추가 하고 strings.xml. 다음 app/src으로 각 플레이버에 대한 폴더를 만듭니다 (예제 구조는 아래 참조). 이 디렉토리 안에 res/values/<string resource file name>. 이제 빌드 할 때이 파일이 빌드에 복사되고 앱 이름이 변경됩니다.

파일 구조 :

app/src
   /pro/res/values/meta_data.xml
   /lite/res/values/meta_data.xml

1
이것은 gradle 파일에서 선언하는 것보다 낫습니다. 매력처럼 작동합니다. 감사합니다.
Filip Luchianenco

7

실제로 사용하는 또 다른 옵션은 각 응용 프로그램의 매니페스트를 변경하는 것입니다. 리소스 폴더를 복사하는 대신 각 맛에 대한 매니페스트를 만들 수 있습니다.

sourceSets {
  main {
 }

  release {
    manifest.srcFile 'src/release/AndroidManifest.xml'
 }

  debug {
    manifest.srcFile 'src/debug/AndroidManifest.xml'
 }
}

주체가 될 src main에 주체 AndroidManifest가 있어야합니다. 그런 다음 (src / release / AndroidManifest.xml)과 같은 각 버전에 대한 몇 가지 옵션 만 사용하여 매니페스트를 정의 할 수 있습니다.

<manifest package="com.application.yourapp">
  <application android:icon="@drawable/ic_launcher">
  </application>
</manifest>

디버그의 경우 AndroidManifest (src / debug / AndroidManifest.xml) :

<manifest package="com.application.yourapp">
  <application android:icon="@drawable/ic_launcher2">
  </application>
</manifest>

컴파일러는 매니페스트 병합을 수행하고 각 맛에 대한 아이콘을 가질 수 있습니다.


4

이것은 buildTypes에서 쉽게 수행 할 수 있습니다.

buildTypes {
    debug {
        buildConfigField("String", "server_type", "\"TEST\"")
        resValue "string", "app_name", "Eventful-Test"
        debuggable true
        signingConfig signingConfigs.debug_key_sign
    }

    stage {
        buildConfigField("String", "server_type", "\"STAGE\"")
        resValue "string", "app_name", "Eventful-Stage"
        debuggable true
        signingConfig signingConfigs.debug_key_sign
    }

    release {
        buildConfigField("String", "server_type", "\"PROD\"")
        resValue "string", "app_name", "Eventful"
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        //TODO - add release signing
    }
}

strings.xml에서 app_name을 제거하십시오.


2

먼저 다음 질문에 답하십시오. "사용자가 동일한 장치에 두 가지 유형의 애플리케이션을 모두 설치할 수 있습니까?"

소스를 패치하는 Python 스크립트를 사용합니다. 여기에는 몇 가지 재사용 가능한 기능과 물론이 특정 프로젝트에서 패치해야 할 사항에 대한 지식이 포함되어 있습니다. 따라서 스크립트는 응용 프로그램에 따라 다릅니다.

많은 패치가 있으며 패치를위한 데이터는 Python 사전 (응용 프로그램 패키지 이름 포함, BTW는 Java 패키지 이름과 다름), 플레이버 당 하나의 사전에 보관됩니다.

l10n과 관련하여 문자열은 다른 문자열을 가리킬 수 있습니다.

<string name="app_name">@string/x_app_name_xyz</string>

<string name="x_app_name_default">My Application</string>
<string name="x_app_name_xyz">My App</string>

그것은 일종의 Light vs Pro 버전입니다. 사용자가 둘 다 가질 수 있다고 생각합니다
Alexander Kulyakhtin 2013

그런 다음 앱 패키지 이름을 변경해야합니다 (예 : com.example.mysoft.procom.example.mysoft.light ). 그렇지 않으면 사용자가 같은 장치에 둘 중 하나만 설치할 수 있습니다.
18446744073709551615

그렇게했는데 휴대폰 메뉴에서 "내 앱"과 "내 앱 프로"를 어떻게 얻습니까? 이제 2 개의 앱 (light 및 pro)이 있지만 둘 다 이름이 같습니다. 이를 위해 2 개의 고유 한 앱 이름이 필요합니다. 즉, 말씀하신대로 쉽지 않습니까?
Alexander Kulyakhtin 2013

다른 (다운 투표) 답변에서 언급했듯이 AndroidManifest.xml에는 <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >. 모든 것을 정리하고 다시 빌드 한 후 (플레이버 당 한 번씩 두 번), 다른 Android 패키지 이름과 다른 실행기 레이블을 가진 두 개의 apk를 가져와야합니다. BTW, Eclipse는 종종 리소스의 변경을 감지하지 않으므로 정리를 요청해야합니다.
18446744073709551615 2013

그래도 문자열 / app_name을 플레이버별로 어떻게 다르게 만들 수 있습니까? 아직도 못 알아서 미안 해요.
Alexander Kulyakhtin 2013

0

그래도 문자열 / app_name을 플레이버별로 어떻게 다르게 만들 수 있습니까?

업데이트를 작성하고 싶었지만 소스를 패치하는 Python 스크립트를 사용한다는 원래 답변보다 크다는 것을 깨달았습니다.

Python 스크립트에는 디렉토리 이름 인 매개 변수가 있습니다. 이 디렉토리에는 유형별 자산, 실행기 아이콘과 같은 리소스, Python 사전이있는 properties.txt 파일이 포함되어 있습니다.

{ 'someBoolean' : True
, 'someParam' : 'none'
, 'appTitle' : '@string/x_app_name_xyz'
}

파이썬 스크립트를로드하는 파일에서 사전을 사이에 값을 대체 <string name="app_name">하고 </string>의 값에 의해 properties['appTitle'].

아래 코드는있는 그대로 /있는 그대로 제공됩니다.

for strings_xml in glob.glob("res/values*/strings.xml"):
    fileReplace(strings_xml,'<string name="app_name">',properties['appTitle'],'</string>',oldtextpattern=r"[a-zA-Z0-9_/@\- ]+")

하나 이상의 이러한 파일에서 속성을 읽으려면 :

with open(filename1) as f:
    properties = eval(f.read())
with open(filename2) as f:
    properties.update(eval(f.read()))

fileReplace 함수는 다음과 같습니다.

really = True
#False for debugging

# In the file 'fname',
# find the text matching "before oldtext after" (all occurrences) and
# replace 'oldtext' with 'newtext' (all occurrences).
# If 'mandatory' is true, raise an exception if no replacements were made.
def fileReplace(fname,before,newtext,after,oldtextpattern=r"[\w.]+",mandatory=True):
    with open(fname, 'r+') as f:
        read_data = f.read()
        pattern = r"("+re.escape(before)+r")"+oldtextpattern+"("+re.escape(after)+r")"
        replacement = r"\g<1>"+newtext+r"\g<2>"
        new_data,replacements_made = re.subn(pattern,replacement,read_data,flags=re.MULTILINE)
        if replacements_made and really:
            f.seek(0)
            f.truncate()
            f.write(new_data)
            if verbose:
                print "patching ",fname," (",replacements_made," occurrence" + ("s" if 1!=replacements_made else ""),")",newtext,("-- no changes" if new_data==read_data else "-- ***CHANGED***")
        elif replacements_made:
            print fname,":"
            print new_data
        elif mandatory:
            raise Exception("cannot patch the file: "+fname+" with ["+newtext+"] instead of '"+before+"{"+oldtextpattern+"}"+after+"'")

스크립트의 첫 번째 줄은 다음과 같습니다.

#!/usr/bin/python
# coding: utf-8

import sys
import os
import re
import os.path
import shutil
import argparse
import string
import glob
from myutils import copytreeover

-4

AndroidManifest 파일의 애플리케이션 태그에는 다음 행이 있습니다.

android:label

그리고 거기에서 응용 프로그램 레이블이 장치의 응용 프로그램 메뉴에 표시되는 방법을 말할 수 있습니다.


예, 질문을 읽었습니다. AndroidManifest 파일에서 다른 android : label을 설정하기 위해 2 개의 브랜치를 설정할 수 있습니다.
Hitman 2013

6
아, 몰랐어요. 그래도 2 개의 매니페스트 파일을 어떻게 배치합니까? 나는 불가능하지만
Alexander Kulyakhtin 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.