我有2种构建口味,比如说, flavor1 和 flavor2 。
当我为flavor2构建时,我希望将我的应用程序命名为“ AppFlavor1 ”,而当我为flavor 2构建时,我希望命名为“ AppFlavor2 ”。
这不是我想要改变的活动的标题。我想更改应用程序名称,因为它显示在手机菜单和其他地方。
从build.gradle
我可以为我的口味设置各种参数,但似乎不是应用标签。而且我也无法根据某些变量以编程方式更改app标签。
那么,人们如何处理这个问题?
答案 0 :(得分:201)
从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!
答案 1 :(得分:18)
为什么不依赖于Android 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
字符串。还有其他我想改变的地方!
答案 2 :(得分: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
答案 3 :(得分:5)
我实际使用的另一个选项是更改每个应用程序的清单。您可以为每种风格创建清单,而不是复制资源文件夹。
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 :(得分:5)
如果您想以不同的方式维护应用名称的本地化,那么您可以按如下方式实现:
1)在android:label
中的<application>
中指定AndroidManifest.xml
,如下所示:
<application
...
android:label="${appLabel}"
...
>
2)在应用级appLabel
中指定默认值fo build.gradle
:
manifestPlaceholders = [appLabel:"@string/defaultName"]
3)按如下方式覆盖产品口味的值:
productFlavors {
AppFlavor1 {
manifestPlaceholders = [appLabel:"@string/flavor1"]
}
AppFlavor2 {
manifestPlaceholders = [appLabel:"@string/flavor2"]
}
}
4)为strings.xml
中的每个字符串(defaultName,flavor1,flavor2)添加字符串资源。这将允许您本地化它们。
答案 5 :(得分: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>
答案 6 :(得分:1)
这可以在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
答案 7 :(得分:0)
如何使每个风格的字符串/ app_name不同?
我想写一个更新,但意识到它比原来的答案更大,说我使用的是修补源代码的Python脚本。
Python脚本有一个参数,一个目录名。该目录包含每个风味资产,启动器图标等资源以及带有Python字典的文件properties.txt。
{ 'someBoolean' : True
, 'someParam' : 'none'
, 'appTitle' : '@string/x_app_name_xyz'
}
Python脚本从该文件加载字典,并将<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
答案 8 :(得分:-3)
在AndroidManifest文件中,在应用程序标记中有这一行:
android:label
在那里你可以说如何在设备的应用程序菜单中显示应用程序标签