Android 5.0+应用内多语言切换失效,asset资源切换失效,bundle包多语言失效

今天在开发完app后打算在Android5.0(api22)的模拟器上面好好测试以下,结果已测试就测出了问题,软件首次启动一切正常,能正确读取到系统语言,也能在应用内切换语言,但是后面无论启动多少次都是系统默认语言,举个例子,系统语言是英文的,首次启动后在应用内把应用语言切换到中文,到此为止一切正常,但是把软件清掉重启,语言就会变成英语。

先把现象说出来,慢慢分析以下:
UI现象:第二次启动后,无论上一次的语言设置为什么语言,都会变成系统语言,但是加载的assets目录下的资源文件未受影响,但是在应用内切换语言是正常的,只是启动后会变成系统语言。

分析:
1.第一次启动正常是因为首次启动会在语言设置界面先选择语言,语言混乱之后在应用内切换语言也能正常,说明切换语言的地方并没有问题,那么要看一下启动时设置语言和应用内切换语言的地方调用的代码有何不同。
2.通过简单的看代码得出,启动时设置语言调用的代码和切换语言调用的代码相同,那么就可以确定设置语言的代码时没有问题的,接着看是不是读取语言设置的地方有问题呢?那么就要分别debug看一下在启动时设置语言的地方传入的语言配置是什么语言,与应用切换语言时传入的语言配置有何不同。
3.通过debug分析得出,都一样,系统语言为英文,启动时传入的语言配置也是我设置的中文配置zh_CN,和应用内切换语言的地方一样,到此基本可以排除是代码的语言造成的多语言失效,同时这种现象只出现在Android 5.x左右(我只测试了Android5.1和Android 8.0)但是还不能完全排除是代码的原因,需要继续分析,那么是不是模拟器的原因呢?。
4.在网上找了个应用内多语言切换的demo,在本地跑起来后能正常切换,软件重启后也正常,说明人家的项目没有问题,排除模拟器的原因,自己再新建一个项目,直接把别人demo里的工具栏copy过来实现应用内多语言切换,发现又出现了这个问题,重启后多语言失效,那么现在问题就简单了,看看别人的demo和我新建的项目有何不同。
5.比对代码发现一处,别人的Activity是集成的Activity,而我的是继承的AppCompatActivity,试着改一下,看是不是这个问题,改了以后发现问题解决了,nice!回到我的项目,发现我的baseActivity也是继承的AppCompatActivity,但是这个改动就有点大了,有点怂,先不急着改,看看有么有别的方案,实在不行再来改这个,接着分析。
6.代码是copy过来的,执行的流程也一样,那就只能是配置的原因,通过比对配置文件发现有一处比较可疑,

implementation 'androidx.appcompat:appcompat:1.0.2'

别人使用的版本和我新建项目使用的不同,我的是1.1.2,别人的是1.0.2,试着改一下看看,发现我新建的项目正常了,问题基本定位,发现原来的项目的这个依赖的版本也不是1.0.2,改过来以后,一切正常,bug解决。
7.接着看一下1.0.2有何特殊之处,网上搜一下就可以找到很多相关的内容,总的来说,就是这个是这个依赖的bug,官方不知道是没发现还是发现了没改,只有1.0.2这个是正常。

总结

网上大多数的多语言切换方案都是没有问题的,有的说要加权限,那个是切换系统语言,并不是再应用内切换多语言,把那个权限加进去就会发现要系统app才能使用这个权限。
切换多语言的工具如下

public class LangUtils {
    
    
    public static final int FOLLOW_SYSTEM = 0;
    private static final int SIMPLE_CHINESE = 1;
    private static final int TRADITION_CHINESE = 2;
    private static final int ENGLISH = 3;

    private static Locale getCurrentLang(int userLang) {
    
    
        switch (userLang) {
    
    
            case SIMPLE_CHINESE:
                return Locale.SIMPLIFIED_CHINESE;
            case TRADITION_CHINESE:
                return Locale.TRADITIONAL_CHINESE;
            case ENGLISH:
                return Locale.ENGLISH;
            case FOLLOW_SYSTEM:
            default:
                return Locale.getDefault();
        }
    }

    public static Context getAttachBaseContext(Context context, int lang) {
    
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    
    
                return updateResources(context, lang);
            } else {
    
    
                //7.0之前的更新语言资源方式
                changeResLanguage(context, lang);
                return context;
            }
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context updateResources(Context context, int lang) {
    
    
        Resources resources = context.getResources();
        Locale locale = getCurrentLang(lang);
        Configuration configuration = resources.getConfiguration();
        configuration.setLocale(locale);
        return context.createConfigurationContext(configuration);
    }

    private static void changeResLanguage(Context context, int lang) {
    
    
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        Locale locale = getCurrentLang(lang);
        configuration.setLocale(locale);
        resources.updateConfiguration(configuration, resources.getDisplayMetrics());
    }

}

调用方法,再所有的Activity里调用,或者写在BaseActivity里也可以,fragment里不用写,只需要写在负责管理它的activity里就行

    @Override
    protected void attachBaseContext(Context newBase) {
    
    
        super.attachBaseContext(LangUtils.getAttachBaseContext(newBase,2));
    }

最最重要的一点,其他版本有问题

implementation 'androidx.appcompat:appcompat:1.0.2'

gradle其他配置如下

android{
    
    
...
  default{
    
    
  ...
     resConfigs "en-rUS", "zh-rCN", "zh-rTW"//配置多语言资源包
  }
  ...
  bundle{
    
    //可选
        language{
    
    
            enableSplit false
        }
    }
    ...
}

这个几个配置不要掉,enableSplit false是关闭bundle包语言分包,默认为true,不设置的话安装bundle包不能正常切换多语言,如果是在国内发包,只使用apk的话 就不用配置bundle属性。
最重要!
最重要!
最重要!
最重要!
其他的版本都有问题,只能使用1.0.2

implementation group: 'androidx.appcompat', name: 'appcompat', version: "1.0.2"

猜你喜欢

转载自blog.csdn.net/qq_17282141/article/details/108115996