program story

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

inputbox 2020. 10. 13. 07:44
반응형

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


2 개의 빌드 플레이버, 즉 flavor1flavor2가 있습니다.

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

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

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

그래서 사람들은 이것을 어떻게 처리합니까?


스크립트로 기본 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. 그리고 내가 바꾸고 싶은 다른 것!


strings.xml에서 app_name을 제거합니다 (그렇지 않으면 gradle은 중복 리소스에 대해 불평합니다). 그런 다음 다음과 같이 빌드 파일을 수정합니다.

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

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

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

이 방법을 사용하여 실행중인 프로덕션 앱이 있습니다.

https://play.google.com/store/apps/details?id=co.getintouch.play ( 앱 이름 'InTouch Messenger : Premium Edition'포함)

https://play.google.com/store/apps/details?id=co.getintouch ( 앱 이름 'InTouch Messenger')

productFlavors {
    main{
        resValue "string", "app_name", "InTouch Messenger"
    }

    googlePlay{
        resValue "string", "app_name", "InTouch Messenger: GPE Edition"
    }
   } 

strings.xml에서 app_name을 제거하는 것을 잊지 마십시오!


각 버전에 문자열 리소스 파일을 추가 한 다음 해당 리소스 파일을 사용하여 앱 이름을 변경할 수 있습니다. 예를 들어 내 앱 중 하나에 무료 및 유료 버전이 있습니다. "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) 지정 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. 이를 통해 현지화 할 수 있습니다.


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

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>

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


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

소스를 패치하는 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>

이것은 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을 제거하십시오.


How do I make string/app_name different per flavor though?

I wanted to write an update, but realized that it is bigger than the original answer saying that I use a Python script that patches the source.

The Python script has a parameter, a directory name. That directory contains per-flavor assets, resources like launcher icons, and the file properties.txt with a Python dictionary.

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

The Python script loads the dictionary from that file and replaces the value between <string name="app_name"> and </string> by the value of properties['appTitle'].

The below code is provided on the as-is/as-was basis etc.

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_/@\- ]+")

to read properties from one or more such file:

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

and the fileReplace function is:

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+"'")

The first lines of the script are:

#!/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

In AndroidManifest file, in the application tag you have this line:

android:label

And there you can say how to application label will appear in applications menu on device

참고URL : https://stackoverflow.com/questions/19830972/different-app-names-for-different-build-flavors

반응형