我有两个构建变体,分别为flavor1和flavor2。
当我针对flavor1进行构建时,我希望我的应用程序被命名为"AppFlavor1",而在构建flavor2时,则命名为"AppFlavor2"。
我想要更改的不是活动的标题,而是应用程序在电话菜单和其他地方显示的名称。
从build.gradle
中,我可以为我的变体设置各种参数,但似乎无法更改应用程序标签。我也无法基于某些变量编程更改应用程序标签。
那么,人们如何处理这个问题呢?
从strings.xml
中删除app_name
(否则gradle会报告重复资源)。然后像这样修改构建文件:
productFlavors {
flavor1{
resValue "string", "app_name", "AppNameFlavor1"
}
flavor2{
resValue "string", "app_name", "AppNameFlavor2"
}
}
同时确保在清单文件的android:label
属性中分配了@string/app_name
值。
<application
...
android:label="@string/app_name"
...
与创建不同的内置集下的新strings.xml
或编写自定义脚本相比,这种方法对系统影响较小。
为避免使用脚本更改您的主要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'
}
}
现在我可以在variants/[release|debug]/res/strings.xml
中定义我的app_name
字符串。还可以改变我想要改变的任何其他内容!
sourceSets
块?是在android{...}
块下面吗? - Abel Callejoandroid
块内。 - Pierre-Luc Paour<application
...
android:label="${appLabel}"
...
>
2) 在应用级别的build.gradle
中指定appLabel
的默认值:
manifestPlaceholders = [appLabel:"@string/defaultName"]
3) 如下覆盖产品风格的值:
productFlavors {
AppFlavor1 {
manifestPlaceholders = [appLabel:"@string/flavor1"]
}
AppFlavor2 {
manifestPlaceholders = [appLabel:"@string/flavor2"]
}
}
4) 在你的strings.xml
中为每一个String(defaultName、flavor1和flavor2)添加字符串资源。这将允许你进行本地化。
<application>
元素中也添加了tools:replace="android:label"
属性。 - rineezmeta_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
main
的资源。本地化按预期工作,例如 /pro/res/values-es/strings.xml
。如果您想要一个回退,也可以在 main 的 strings.xml 中保留 app_name
。应该是被接受的答案。 - sulai另一个选项是为每个应用程序更改清单。而不是复制资源文件夹,可以为每个风味创建一个清单。
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>
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。
<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>
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >
。在你清理并重新构建所有内容后(每个口味一次),你应该得到两个具有不同Android包名称和不同启动器标签的apk文件。顺便说一句,Eclipse经常无法检测到资源的更改,因此您必须要求它进行清理。 - 18446744073709551615这很容易实现。如果您已经在您的应用程序中创建了不同版本,并且应用程序名称是从AndroidManifest.xml
获取的。假设
<application
android:name="com.prakash.sampleapp"
android:label="@string/app_name">
你只需要为你的口味创建string/app_name
。
app/src
,选择New>XML>Values XML File
Target Source Set
并创建strings.xml
文件。app_name
更新为您喜欢的名称。./gradlew installFlavorNameDebug
,您将看到应用程序的更新名称。您也可以手动创建strings.xml
,但使用上述方法,AS会更轻松地为您创建所有目录和资源文件。
如何使每个风味的字符串/应用程序名称不同?
我想写一个更新,但意识到它比原来的答案更大,因为我使用了一个修补源代码的Python脚本。
Python脚本有一个参数,即目录名称。该目录包含每个风味的资源,例如启动器图标和文件properties.txt,其中包含一个Python字典。
{ '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
@string/app_name
?请注意,主启动器activity
的标签优先于应用程序名称(application label
)用于应用程序显示名称。 - user650881