Android 获取设备区域设置

Posted

技术标签:

【中文标题】Android 获取设备区域设置【英文标题】:Android get device locale 【发布时间】:2014-06-14 11:07:53 【问题描述】:

安装我的 android 程序后,我会检查设备区域设置:

String deviceLocale=Locale.getDefault().getLanguage();

如果 deviceLocale 在我支持的语言(英语、法语、德语)内,我不会更改语言环境。

但是例如说如果我不支持设备的语言:例如西班牙语。 我将当前语言环境设置为英语,因为大多数人都能部分理解英语。

Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
pContext.getResources().updateConfiguration(config, null);

但在那之后,在其他方法中,当我像这样检查设备的语言环境时:

String deviceLocale=Locale.getDefault().getLanguage();

我得到的结果是“英语”。但是设备的语言环境是西班牙语。

getLanguage() 是否提供当前应用的语言环境? 如何获取设备的语言环境?

编辑:在应用程序的第一次运行中,它是保存设备区域设置的选项。但是如果用户在我保存后更改了设备区域设置,我就无法知道设备的新区域设置。我只能知道我在应用安装中保存的语言环境。

【问题讨论】:

如果您在设置后获得默认语言环境...you get what you set。可以选择在更改之前保存区域设置(例如,更改为 SharedPreference),以便稍后恢复 - 如果您需要返回。 但是当我返回并加载我保存的区域设置值时,我得到了最新的已知设备区域设置。但是保存后,如果用户更改设备区域设置,我无法知道设备的当前区域设置? 这很好。我的有点像黑客。我仍然相信您在手机生活中多次更改设备区域设置并没有什么乐趣......或者更“有趣”,每天不止一次。无论如何,你是对的 - 我的 hack 并没有真正解决问题。 一般来说,最好修改现有对象而不是创建自己的对象,而只需修改现有对象中的字段。现在,当您创建新的Configuration 对象时,构造函数在内部调用setToDefaults()。如果您不小心,这可能会覆盖您在其他地方对配置所做的一些更改。这与您的问题无关,但只是一个很好的经验法则。所以不要创建一个新对象,而是调用getResources().getConfiguration() 您可以检测到侦听LOCALE_CHANGED 广播的区域设置更改。但意图似乎不包括新的语言环境,因此您将不得不依靠@shoe 答案来获取新的语言环境。 【参考方案1】:

有一种比使用反射或解析某些系统属性更简单、更简洁的方法。

正如您所注意到的,一旦您在应用中设置了默认区域设置,您就无法再访问系统默认区域设置。您在应用中设置的默认 Locale 仅在应用的生命周期内有效。一旦进程终止,您在 Locale.setDefault(Locale) 中设置的任何内容都将消失。当应用程序重新启动时,您将再次能够读取系统默认区域设置。

因此,您需要做的就是在应用启动时检索系统默认区域设置,只要应用运行就记住它,并在用户决定更改 Android 设置中的语言时更新它。因为只有在应用程序运行时我们才需要该信息,我们可以简单地将其存储在一个静态变量中,该变量可从应用程序的任何位置访问。

我们是这样做的:

public class MyApplication extends Application 
    
    public static String sDefSystemLanguage;
    
    @Override
    public void onCreate() 
        super.onCreate();

        sDefSystemLanguage = Locale.getDefault().getLanguage();
    

    @Override
    public void onConfigurationChanged(Configuration newConfig) 
        super.onConfigurationChanged(newConfig);

        sDefSystemLanguage = newConfig.locale.getLanguage();
    


使用应用程序(不要忘记在清单中定义它)我们会在应用程序启动时获得默认语言环境 (onCreate()),并在用户更改 Android 设置中的语言时更新它 (onConfigurationChanged(Configuration ))。这就是全部。 每当您在使用 setDefault 调用之前需要知道系统默认语言是什么时,sDefSystemLanguage 都会给您答案。

我在您的代码中发现了一个问题。当您设置新的语言环境时:

Configuration config = new Configuration();
config.locale = locale;
pContext.getResources().updateConfiguration(config, null);

当你这样做时,你会覆盖你可能想要保留的所有配置信息。例如。 Configuration.fontScale 反映了辅助功能设置大文本。通过设置语言并丢失所有其他配置,您的应用将不再反映大文本设置,这意味着文本小于应有的大小(如果用户启用了大文本设置)。 正确的做法是:

Resources res = pContext.getResources();
Configuration config = res.getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) 
    configuration.setLocale(locale);

else 
    configuration.locale = locale;

res.updateConfiguration(config, null);

因此,我们只需更新当前的配置对象,而不是创建新的配置对象。

【讨论】:

感谢您提供有关new Configuration()问题的信息和其他信息。 这真的很详细。喜欢细节,样品无处不在!【参考方案2】:

更新:正如 cmets 中指出的那样,'locale' 字段已弃用,您需要改用 getLocales()。

defaultLocale = Resources.getSystem().getConfiguration().getLocales().get(0);

----------------------------------------------- ---------------------------

您可以通过 -

访问全局语言环境

defaultLocale = Resources.getSystem().getConfiguration().locale;

看看http://developer.android.com/reference/android/content/res/Resources.html#getSystem()-

返回一个全局共享资源对象,该对象仅提供对系统资源(无应用程序资源)的访问权限

【讨论】:

这是正确的解决方案! Locale.getDefault().getLanguage() 将给出您的应用设置的,而不是手机的语言 我花了很长时间才找到这条评论!这就是我一直在寻找的,如何获取设备默认语言,然后根据此更改应用程序的语言。谢谢!【参考方案3】:

设计应用程序的最佳方式是在 values/ 下使用默认语言(在您的情况下为英语),您可以在 values-XX/ 下添加其他语言。这样,当一种语言不支持时,Android 会回退到您的默认设置,即英语。让操作系统为您完成工作 :) 但是,是的,如果您更改语言环境,您将获得最后的设置,因此您必须将该信息保存在某处。

【讨论】:

【参考方案4】:

当您更改时 Application language programatically like

Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
pContext.getResources().updateConfiguration(config, null);

还有

But after that, in other methods, when I check device's locale like this:

String deviceLocale=Locale.getDefault().getLanguage();
I get result as "English". But device's locale is Spanish.

因此,请使用以下代码获取 device's Local

try 
    Process exec = Runtime.getRuntime().exec(new String[]"getprop", "persist.sys.language");
    String locale = new BufferedReader(new InputStreamReader(exec.getInputStream())).readLine();
    exec.destroy();
    Log.e("", "Device locale: "+locale);
 catch (IOException e) 
    e.printStackTrace();

输出: Spanish Check this

希望这正是您正在寻找的。​​p>

【讨论】:

【参考方案5】:

你应该使用String deviceLocale= Locale.getDefault().getDisplayLanguage();来显示语言而不是

String deviceLocale=Locale.getDefault().getLanguage();

看看这个答案,如果上面没有,它可能会对你有所帮助。 Clickable

【讨论】:

【参考方案6】:

虽然@user2944616 的回答在政治上是正确的,但这并不能回答所提出的实际问题。

所以,如果我真的必须知道用户设置的系统区域设置,我会使用反射(不知道任何更好的选项 ATM):

private String getSystemPropertyValue(String name) 
    try 
        Class<?> systemProperties = Class.forName("android.os.SystemProperties");
        try 
            Method get = systemProperties.getMethod("get", String.class, String.class);
            if (get == null) 
                return "Failure!?";
            
            try 
                return (String)get.invoke(systemProperties, name, "");
             catch (IllegalAccessException e) 
                return "IllegalAccessException";
             catch (IllegalArgumentException e) 
                return "IllegalArgumentException";
             catch (InvocationTargetException e) 
                return "InvocationTargetException";
            
         catch (NoSuchMethodException e) 
            return "SystemProperties.get(String key, String def) method is not found";
        
     catch (ClassNotFoundException e) 
        return "SystemProperties class is not found";
    

将给定的设备语言环境设置为西班牙语(美国)/西班牙语(Estados Unidos),跟随字符串

<string name="system_locale">System locale: <xliff:g id="profile_name">%1$s</xliff:g>&#95;<xliff:g id="device_name">%2$s</xliff:g></string>

还有这段代码

private static final String SYS_COUNTRY = "persist.sys.country";
private static final String SYS_LANG = "persist.sys.language";

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    TextView tv = (TextView)findViewById(R.id.locale);
    tv.setText(getString(R.string.system_locale, getSystemPropertyValue(SYS_LANG),
            getSystemPropertyValue(SYS_COUNTRY)));

产生以下屏幕:

如果需要,也可以使用上述方法轻松构造Locale 实例:

Locale locale = new Locale(getSystemPropertyValue(SYS_LANG),
        getSystemPropertyValue(SYS_COUNTRY));
Log.d(TAG, "Language: " + locale.getLanguage());
Log.d(TAG, "Country: " + locale.getCountry());

日志输出:

D/GetSystemLocale(5697): Language: es
D/GetSystemLocale(5697): Country: US

希望这会有所帮助。

【讨论】:

对我来说,这似乎是最好的方法。避免反射的一种方法是只执行getprop 命令并解析输出。你也可以得到TTS系统的Country和Language。 TTS 引擎的默认语言可能很容易与系统区域设置不同。【参考方案7】:

要获取设备区域设置,请使用此

Locale current = context.getResources().getConfiguration().locale;

current.toString() 将返回“en”“ar”等

【讨论】:

以上是关于Android 获取设备区域设置的主要内容,如果未能解决你的问题,请参考以下文章

Android获取当前区域设置,而不是默认设置

在设备中设置系统区域设置

Unity Android设备的输入

Android 经典蓝牙开发(一)

Android Nougat 7.1 在启动 WebView 后重置区域设置

Android适配不同的设备