使用resConfig

时间:2015-07-22 14:35:36

标签: android gradle localization locale android-productflavors

我正在尝试使用Android Build系统中的resConfig和resConfigs。

  • Android Studio版本1.2.2
  • Gradle build版本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(默认)
  /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 /
  /值-FR /

虽然所有语言值文件夹仍在那里,所以resConfigs没有明显过滤任何内容。

我还希望在运行enDebug flavor变量时从values-en看到标签hello_world,因为我指定了flavor en将使用resConfig" en"虽然当我运行测试应用程序时,我看到来自/values-fr/strings.xml的标签而不是/values-en/strings.xml,因为平板电脑上的语言被配置为法国加拿大

我是否误解了resConfig背后的目的?如果是这样,我应该如何强制只使用语言运行并且不依赖于操作系统区域设置?此解决方案必须与flavorDimensions兼容,因为我在尝试配置的真实应用程序中使用它们。

注意:我还提交了一个错误,因为我认为此resConfig行为确实存在问题https://code.google.com/p/android/issues/detail?id=180694

由于

2 个答案:

答案 0 :(得分:9)

好吧,经过好几个小时之后,对于那些遇到同样问题的人来说,这就解决了我的问题。

事实证明,resConfig不适合我。我发现强制特定风味的语言环境的正确和唯一方法是这样的:

首先,确保您的所有活动都扩展了一个共同的活动,该活动将负责强制使用区域设置。 (我必须创建2,因为我有一些活动扩展了FragmentActivity和一些扩展Activity。我也不喜欢在Activities构造函数中这样做但是因为我必须在getResources上完成任何调用之前调用applyOverrideConfiguration,I需要在活动的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 flavor中定义区域设置

productFlavors {

    myFrenchFlavor {
     buildConfigField "String", "LOCALE", "\"fr\""
    }
    myEnglishFlavor {
      buildConfigField "String", "LOCALE", "\"en\""
    }
}

我在API 19+上测试了该解决方案。在应用程序中更改语言时也可以使用。



备用解决方案不适用于Android M + see android bug report ) 这个解决方案在stackOverflow上广泛传播,但我在Android M上实现这个时遇到了障碍,所以请记住这一点。

在AndroidApplication的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团队目前正致力于此!

感谢。

答案 1 :(得分:1)

resConfig不会覆盖resConfigs的指定defaultConfig,而只是将它们组合起来。因此,您最终将获得包含en fr资源的所有口味。

因此,为避免这种情况,您不应在resConfigs中指定任何defaultConfig,只需将其设置为特定的风格。

此外,应用程序将始终包含默认values,这意味着如果您有英语字符串,fr风格仍将显示在设置为任何非法语的设备上的英语内容区域设置。