使用 resConfig 为 Android 风味强制区域设置
Force locale for Android flavor with resConfig
我正在尝试使用 Android 构建系统中的 resConfig 和 resConfigs。
- Android Studio 版本 1.2.2
- Gradle 构建版本 1.2.3
- OSX 10.10.3
我在我的项目中遇到了这两个选项的问题,所以我用 android studio 开始了一个新的空白项目。我附上了 build.gradle,我只在
下添加了 resConfigs "en"、"fr"
android {
defaultConfig {
...
resConfigs "en", "fr"
...
}
}
并定义了 2 种基本口味
productFlavors {
fr {
resConfig "fr"
}
en {
resConfig "en"
}
}
然后我创建了 2 个 strings.xml 文件并翻译了 hello_world 默认标签
/src/main/res/values/strings.xml (default)
/src/main/res/values-en/strings.xml
/src/main/res/values-fr/strings.xml
有了这个,我希望在 MyApplication/app/builds/intermediates/res/en/debug 中只看到 3 个值文件夹,因为我在 resConfigs 中定义为仅使用 "en" 和 "fr" 并过滤任何其他内容
/values/
/values-en/
/values-fr/
尽管如此,所有语言值文件夹仍在那里,因此 resConfigs 显然没有过滤任何内容。
我还希望在 运行ning enDebug flavor 变体时看到来自 values-en 的标签 hello_world 因为我指定 flavor en 将使用 resConfig "en" 尽管当我运行 测试应用我看到的标签来自 /values-fr/strings.xml 而不是 /values-en/strings.xml 因为平板电脑上的语言配置为加拿大法语
我是不是误解了 resConfig 背后的目的?如果是这样,我应该如何强制仅使用 运行 语言而不依赖于 OS 语言环境设置?此解决方案也必须与 flavorDimensions 兼容,因为我在我尝试配置的真实应用程序中使用它们。
注意:我还提交了一个错误,因为我认为这个 resConfig 行为确实存在问题 https://code.google.com/p/android/issues/detail?id=180694
谢谢
好吧,几个小时后,对于那些最终遇到同样问题的人,这里是我的问题的解决方案。
原来 resConfig 不是我想的那样。我发现为特定风格强制语言环境的正确且唯一的方法是这样的:
首先,确保您所有的活动都扩展了一个共同的 activity,它将负责强制使用语言环境。 (我必须创建 2,因为我有一些扩展 FragmentActivity 的活动和一些扩展 Activity 的活动。我也不太喜欢在 Activities 构造函数中这样做,但因为我必须在对 getResources 进行任何调用之前调用 applyOverrideConfiguration,我需要在 activity 的 onStart).
之前调用它
public class LocaleMainActivity extends Activity {
public LocaleMainActivity() {
ActivityUtils.forceLocale(this);
}
}
public class LocaleMainFragmentActivity extends FragmentActivity {
public LocaleMainFragmentActivity() {
ActivityUtils.forceLocale(this);
}
}
//Method from ActivityUtils
public static void forceLocale(ContextThemeWrapper contextThemeWrapper) {
Configuration configuration = new Configuration();
Locale defaultLocale = new Locale(BuildConfig.LOCALE);
configuration.locale = defaultLocale;
contextThemeWrapper.applyOverrideConfiguration(configuration);
}
接下来,您需要在 build.gradle 风格中定义语言环境
productFlavors {
myFrenchFlavor {
buildConfigField "String", "LOCALE", "\"fr\""
}
myEnglishFlavor {
buildConfigField "String", "LOCALE", "\"en\""
}
}
我在 API 19+ 上测试了解决方案。当您在应用程序中更改语言时也适用。
替代解决方案(不适用于Android M+ see android bug report)
这个解决方案在 Whosebug 上广泛传播,但我在 Android M 上实现它时遇到了困难,所以请记住这一点。
在您的 Android应用程序的 onCreate() 中,您可以使用区域设置调用 updateConfiguration。
Locale myLocale = new Locale(BuildConfig.LOCALE);
Resources res = getResources();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, res.getDisplayMetrics());
如果您定义了 onConfigurationChanged()
,您还需要重置它
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Configuration config = new Configuration(newConfig);
config.locale = new Locale(BuildConfig.LOCALE);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
编辑: 请注意,此 applyOverrideConfiguration 目前有一个副作用,在此处 Chromium webview does not seems to work with Android applyOverrideConfiguration 进行了解释。 Chromium 团队目前正在努力解决这个问题!
谢谢。
resConfig
不会覆盖 defaultConfig
的指定 resConfigs
,而只是组合它们。因此,您最终会得到包含 en
和 fr
资源的所有口味。
因此,为避免这种情况,您不应在 defaultConfig
中指定任何 resConfigs
,只需将其设置为特定风格即可。
此外,该应用程序将始终包含默认 values
,这意味着如果您那里有英文字符串,fr
风格仍会在设置为任何非英语内容的设备上显示英文内容-法语语言环境。
我正在尝试使用 Android 构建系统中的 resConfig 和 resConfigs。
- Android Studio 版本 1.2.2
- Gradle 构建版本 1.2.3
- OSX 10.10.3
我在我的项目中遇到了这两个选项的问题,所以我用 android studio 开始了一个新的空白项目。我附上了 build.gradle,我只在
下添加了 resConfigs "en"、"fr"android {
defaultConfig {
...
resConfigs "en", "fr"
...
}
}
并定义了 2 种基本口味
productFlavors {
fr {
resConfig "fr"
}
en {
resConfig "en"
}
}
然后我创建了 2 个 strings.xml 文件并翻译了 hello_world 默认标签
/src/main/res/values/strings.xml (default)
/src/main/res/values-en/strings.xml
/src/main/res/values-fr/strings.xml
有了这个,我希望在 MyApplication/app/builds/intermediates/res/en/debug 中只看到 3 个值文件夹,因为我在 resConfigs 中定义为仅使用 "en" 和 "fr" 并过滤任何其他内容
/values/
/values-en/
/values-fr/
尽管如此,所有语言值文件夹仍在那里,因此 resConfigs 显然没有过滤任何内容。
我还希望在 运行ning enDebug flavor 变体时看到来自 values-en 的标签 hello_world 因为我指定 flavor en 将使用 resConfig "en" 尽管当我运行 测试应用我看到的标签来自 /values-fr/strings.xml 而不是 /values-en/strings.xml 因为平板电脑上的语言配置为加拿大法语
我是不是误解了 resConfig 背后的目的?如果是这样,我应该如何强制仅使用 运行 语言而不依赖于 OS 语言环境设置?此解决方案也必须与 flavorDimensions 兼容,因为我在我尝试配置的真实应用程序中使用它们。
注意:我还提交了一个错误,因为我认为这个 resConfig 行为确实存在问题 https://code.google.com/p/android/issues/detail?id=180694
谢谢
好吧,几个小时后,对于那些最终遇到同样问题的人,这里是我的问题的解决方案。
原来 resConfig 不是我想的那样。我发现为特定风格强制语言环境的正确且唯一的方法是这样的:
首先,确保您所有的活动都扩展了一个共同的 activity,它将负责强制使用语言环境。 (我必须创建 2,因为我有一些扩展 FragmentActivity 的活动和一些扩展 Activity 的活动。我也不太喜欢在 Activities 构造函数中这样做,但因为我必须在对 getResources 进行任何调用之前调用 applyOverrideConfiguration,我需要在 activity 的 onStart).
之前调用它public class LocaleMainActivity extends Activity {
public LocaleMainActivity() {
ActivityUtils.forceLocale(this);
}
}
public class LocaleMainFragmentActivity extends FragmentActivity {
public LocaleMainFragmentActivity() {
ActivityUtils.forceLocale(this);
}
}
//Method from ActivityUtils
public static void forceLocale(ContextThemeWrapper contextThemeWrapper) {
Configuration configuration = new Configuration();
Locale defaultLocale = new Locale(BuildConfig.LOCALE);
configuration.locale = defaultLocale;
contextThemeWrapper.applyOverrideConfiguration(configuration);
}
接下来,您需要在 build.gradle 风格中定义语言环境
productFlavors {
myFrenchFlavor {
buildConfigField "String", "LOCALE", "\"fr\""
}
myEnglishFlavor {
buildConfigField "String", "LOCALE", "\"en\""
}
}
我在 API 19+ 上测试了解决方案。当您在应用程序中更改语言时也适用。
替代解决方案(不适用于Android M+ see android bug report)
这个解决方案在 Whosebug 上广泛传播,但我在 Android M 上实现它时遇到了困难,所以请记住这一点。
在您的 Android应用程序的 onCreate() 中,您可以使用区域设置调用 updateConfiguration。
Locale myLocale = new Locale(BuildConfig.LOCALE);
Resources res = getResources();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, res.getDisplayMetrics());
如果您定义了 onConfigurationChanged()
,您还需要重置它@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Configuration config = new Configuration(newConfig);
config.locale = new Locale(BuildConfig.LOCALE);
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
编辑: 请注意,此 applyOverrideConfiguration 目前有一个副作用,在此处 Chromium webview does not seems to work with Android applyOverrideConfiguration 进行了解释。 Chromium 团队目前正在努力解决这个问题!
谢谢。
resConfig
不会覆盖 defaultConfig
的指定 resConfigs
,而只是组合它们。因此,您最终会得到包含 en
和 fr
资源的所有口味。
因此,为避免这种情况,您不应在 defaultConfig
中指定任何 resConfigs
,只需将其设置为特定风格即可。
此外,该应用程序将始终包含默认 values
,这意味着如果您那里有英文字符串,fr
风格仍会在设置为任何非英语内容的设备上显示英文内容-法语语言环境。