我有2种构建口味,例如,flavor1和flavor2。
我想我的应用程序被命名,比如“ AppFlavor1 ”当我建立flavor1和“ AppFlavor2 ”当我建立的味道2。
这不是我要更改的活动的标题。我想更改应用程序名称,因为它显示在电话菜单和其他地方。
从build.gradle
我可以为自己的口味设置各种参数,但似乎不是应用程序标签。而且我也无法基于某些变量以编程方式更改应用程序标签。
那么,人们如何处理呢?
我有2种构建口味,例如,flavor1和flavor2。
我想我的应用程序被命名,比如“ AppFlavor1 ”当我建立flavor1和“ AppFlavor2 ”当我建立的味道2。
这不是我要更改的活动的标题。我想更改应用程序名称,因为它显示在电话菜单和其他地方。
从build.gradle
我可以为自己的口味设置各种参数,但似乎不是应用程序标签。而且我也无法基于某些变量以编程方式更改应用程序标签。
那么,人们如何处理呢?
Answers:
除了使用脚本更改主要的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
。还有其他我想更改的内容!
sourceSets
块?是在android{...}
街区下吗?
android
区块内有@AbelMelquiadesCallejo 。
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
在不同的构建集下创建新的脚本或编写自定义脚本相比,这具有较小的破坏性。
@string/app_name
启动器activity
标签吗?请记住,优先使用label
来自主启动器activity
的application
label
,而不是应用程序显示名称的。
如果要以不同的方式维护应用程序名称的本地化,则可以按以下步骤实现:
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)为中的每个字符串(defaultName,flavor1,flavor2)添加字符串资源strings.xml
。这将允许您本地化它们。
您可以向每种口味添加一个字符串资源文件,然后使用这些资源文件来更改您的应用程序名称。例如,在我的一个应用程序中,我有一个免费版本和付费版本。为了将它们重命名为“ 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
我实际使用的另一个选项是更改每个应用程序的清单。您可以复制每种口味的清单,而不用复制资源文件夹。
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下轻松完成
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
首先,回答以下问题:“用户可以在同一设备上安装两种版本的应用程序吗?”
我使用修补源代码的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>
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >
。清理并重新构建所有内容(两次,每种口味一次)后,您应该获得两个具有不同android软件包名称和不同启动器标签的apk-s。顺便说一句,Eclipse通常不会检测到资源的变化,因此您必须要求它进行清理。
我如何使字符串/ 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
在AndroidManifest文件的application标签中,您具有以下这一行:
android:label
您可以说如何在设备上的应用程序菜单中显示应用程序标签