Android Locale.getDefault().getCountry()为空

最近实际项目中,需要获取手机系统国家地区来做一些特殊逻辑。

很简单嘛,

 public static String getCountry(Context context) {
        TelephonyManager tm = (TelephonyManager) BaseInfo.getSystemService(context, Context.TELEPHONY_SERVICE);
        String country = tm.getSimCountryIso();
        if (TextUtils.isEmpty(country)) {
            country = Locale.getDefault().getCountry();
        }
        if (TextUtils.isEmpty(country)) {
            country = "";
        }
        return country.toUpperCase(Locale.US);
    }

但是最近发现7.0以上部分手机获取为空,发现问题出在Locale.getDefault().getCountry()。

系统API怎么会有这种错误,翻开了API文档和google也没有任何有用信息。仔细思索后觉还是自己的问题,我们app支持18种语言,在启动时会根据系统默认和用户设置来重置语言。仔细翻看这部分代码发现,果然是在切换语言时重新设置了app resource的Locale信息,并在构造Locale时没有填入countryCode。

再通过debug来验证自己的想法,果然Resource中的Locale和Locale#getDefault是一样的。

那么如何去获取到正确的系统国家呢? 一个方法是在设置语言时传入正确的countryCode,但这个也受限于如何判定正确的国家。此外在翻看Resources的api文档发现一个getSystem的静态方法。

注释如下:a global shared Resources object that provides access to only system resources (no application resources), and is not configured for the current screen (can not use dimension units, does not change based on orientation, etc).

我们知道android在启动app进程时,都是从zoyge进程中fork出来。其中为了节约资源,也会将系统的资源"copy"一份,这部分资源就可以通过Resources#getSystem来获取到。那么这里获取到的Locale就是系统中设置的信息。

7.0以上适配

在android 7.0以上,google改变了locale的规则。之前只存在一个locale,而后面是可以支持一个locale list。

在support包中,还有一个帮助类根据Resource获取到Locale信息,避免的N以上的List判断。

ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration())

此外需要注意的是,在8.0 版本如果设置单个Locale可能会导致ActivityThread中NPE crash,需要将单个Locale变成一个List。

Tips: 如何修改手机国家地区? Android中并没有直接设置国家地区的选项,实际可以通过修改显示中语言来完成,N以上办法可以选择多个语言,规则是按照语言排序。

为了保证与以前的Android版本的兼容性,可能的解决方案是一个简单的检查:

 public static String getCountry(Context context) {
        TelephonyManager tm = (TelephonyManager) BaseInfo.getSystemService(context, Context.TELEPHONY_SERVICE);
        String country = tm.getSimCountryIso();
        if (TextUtils.isEmpty(country)) {
            country = getLocale().getCountry();
        }
        if (TextUtils.isEmpty(country)) {
            country = "";
        }
        return country.toUpperCase(Locale.US);
    }

    public static Locale getLocale() {
        Locale locale;
        try {
            LocaleListCompat listCompat= ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration());
            locale= listCompat.get(0);
        }catch (Exception e){
            locale=Locale.getDefault();
        }
        return locale;
    }
posted on 2020-01-15 11:22  mingfeng002  阅读(4554)  评论(0编辑  收藏  举报