切换android系统语言的流程

本文详细剖析了Android系统在切换语言时的流程,包括从Setting界面选择语言到更新系统配置的过程。通过分析关键方法如updateConfigurationLocked和applyConfigurationToResourcesLocked,解释了如何实现语言的切换。并针对特定bug,说明了音乐应用在后台播放时,如何在切换语言后导致通知栏显示通知的问题及其解决方法。

最近在看一个bug,系统切换语言后,本来退到后台的音乐,会在通知栏上显示通知。为了解决这个bug,我学习了下android的语言切换流程,也参考了大量其他人的资料。(主要参考了http://blog.youkuaiyun.com/wqhjfree/article/details/8244520)在这里我将自己的探索记录下来,作为自己的学习记录,也希望能对有同样需要的人有个帮助。刚学android不久,如果中间有什么问题不对的请多多谅解,并指出错误,多交流,共同进步下。

       1.从setting入手,我们可以知道,在setting中,语言设置的入口在一个叫做LocalePicker的类里面,当点击里面的一个语言后会调用 onLocaleSelected(final Locale locale)方法。通过分析这个方法我们可以知道,最后切换语言并不是在这里完成,而是去调用了fromwork下的updateLocale()方法(位于frameworks/base/core/java/com/android/internal/app/LocalePicker)。


     2.居然他是调用的fromwork下LocalePicker类中的updateLocale()方法,我们继续往下看。通过分析,我们知道这个方法也不是一个最终的处理方法,而是去调用了ActivityManagerService.java中的updateConfiguration()函数。


    3.看看updateConfiguration()方法做了什么事情,这里做了一些值得判断和初始工作。最重要的是他调用的updateConfigurationLocked(values, null, false, false)方法;


   4.updateConfigurationLocked中主要做了两件事:(1)改变现在的 configuration(这是一个系统配置的类,有兴趣的可以去了解下);(2)确保所有正在运行的Activity都运行改变后的configuration。下面可以看看他到底是怎么完成这两件事的。首先,通过updateFrom(values)判断是不是真的语言发生了变化,如果改变了,从if条件走,在if里面,前面做一些判断之类的工作,到此也完成了第一步的工作。最重要的是for循环里面的操作,首先得到了所有运行过的app的集合,然后对每个app调用scheduleConfigurationChanged()方法,进行语言的切换工作。


  5.scheduleConfigurationChanged是在ActivityThread中,这个方执行了 updatePendingConfiguration(config)和 queueOrSendMessage(H.CONFIGURATION_CHANGED, config)两个方法。前面一个方法是更新Configuration;最主要的操作在queueOrSendMessage()里面的handleConfigurationChanged((Configuration)msg.obj, null)方法中。


6.接着对handleConfigurationChanged进行分析,从中我们不难发现applyConfigurationToResourcesLocked()这个是一个重新配置资源的函数,performConfigurationChanged(callbacks.get(i), config)这个方法是执行Configuration的改变。即最终完成语言的切换。


7.详细的分析下applyConfigurationToResourcesLocked做了哪些工作,updateFrom(config) 把config更新到Configuration中,后面 最主要的是在while () 中做了资源更新和删除就资源的操作。


8.performConfigurationChanged方法中,这是完成语言切换的最后一步了,首先判断当前activity的config和新的config是否一样,如果是一样什么都不做;如果不一样,则重启app,重新加载资源达到切换语言。


9.总结语言切换的大概流程是,判断configuration中的local即语言是不是有改变,如果有改变即为要切换语言。执行切换语言的时候,对那些已经运行过的程序,执行一个资源的清除和重新加载的过程,就完成了整个系统的语言切换。


最后,那个bug也就迎刃而解了,music运行之后,切换语言,他销毁了一次,又重新启动了,导致状态栏上有了通知提示

<think>首先,用户的问题是:“我想了解Android系统切换语言功能实现所需要经历哪些步骤 请问Android切换语言功能实现流程”。用户提供了四个引用,我需要参考这些引用来回答。 引用内容总结: - [^1]:讨论了Android 12.0中系统语言切换的实现,涉及核心类如IActivityManager.aidl、ActivityManagerService.java、ActivityTaskManagerService.java。 - [^2]:在Android 11.0中,通过ActivityTaskManagerService.updatePersistentConfiguration()来改变系统语言,并给出了一个自定义服务接口的代码示例。 - [^3]:提到在manifest中设置android:configChanges="locale|layoutDirection"来避免应用重启。 - [^4]:关于应用内语言切换,保存语言设置到SharedPreferences。 用户想知道实现Android系统切换语言功能所需经历的步骤。我应该提供一个清晰、结构化的流程,基于这些引用和一般知识。 关键点: - 系统语言切换涉及Framework层,如ActivityManagerService。 - 应用级可能需要处理配置变化,避免重启。 - 流程包括:获取当前配置、设置新语言、更新配置、持久化存储。 步骤分解: 1. **初始化或获取当前配置**:获取系统当前的Configuration对象,其中包含语言设置。 2. **设置新语言**:创建一个新的Locale对象表示目标语言,并将其设置到Configuration中。 3. **更新系统配置**:通过系统服务(如IActivityManager)调用更新方法,如updatePersistentConfiguration()。 4. **处理应用重启**:系统默认会重启应用以应用新语言,但可以通过在manifest中配置来避免。 5. **持久化存储**:保存语言设置到持久化存储(如SharedPreferences或系统设置),以便下次启动时应用。 6. **通知应用更新**:系统会广播配置变化,应用需要处理onConfigurationChanged回调。 基于引用[^2],核心实现是调用am.updatePersistentConfiguration(config)。引用和[^4]涉及应用层处理。 完整流程: - 系统级别:Framework服务处理配置更新。 - 应用级别:应用响应配置变化。 回答结构: - 逐步解释流程。 - 使用中文。 - 引用末尾添加引用标识。 - 生成相关问题。 - 确保LaTeX语法正确,但用户问题中没有数学表达式,所以可能不需要LaTeX。 - 代码块如果适用。 最终回答应包括: 1. **介绍**:简要概述流程。 2. **详细步骤**:分步描述。 3. **代码示例**:基于引用[^2]提供简单示例。 4. **应用层处理**:如何避免重启。 5. **生成相关问题**。 生成相关问题: - 基于主题,如如何优化、常见问题等。 相关问题想法: 1. 如何避免应用重启时切换语言? 2. Android系统语言切换的性能影响是什么? 3. 如何在自定义应用中实现多语言切换? 4. 系统语言切换与用户界面的交互? 5. 如何处理不同Android版本的语言切换差异? 确保回答真实可靠:基于提供的引用和一般Android知识。 </think> 以下是关于Android系统切换语言功能实现流程的详细解释。我将基于您提供的引用内容(特别是[^1]和)以及Android Framework的标准实现,逐步说明所需经历的步骤。实现系统语言切换主要涉及Framework层的核心服务(如ActivityManagerService),流程包括配置更新、系统广播和应用处理。整个过程分为系统级步骤和应用级适配步骤。 ### 系统语言切换实现流程 Android系统语言切换的核心是通过Framework服务修改系统配置(Configuration),并广播变化通知应用更新。以下是主要步骤,基于引用[^1]和[^2]的分析: 1. **获取当前系统配置** 从Framework层获取当前的Configuration对象,该对象包含语言、区域等设置。通常通过系统服务(如Resources或ActivityManager)访问。 - 示例代码(基于引用): ```java Configuration config = ctx.getResources().getConfiguration(); // 获取当前配置 ``` 2. **创建并设置新语言Locale** 根据目标语言(如"zh"表示中文、"en"表示英文),创建一个Locale对象,并更新到Configuration中。设置`userSetLocale`标志表示用户手动更改语言。 - 关键点:Locale对象定义语言和地区(可选),例如`new Locale("zh")`或`new Locale("en", "US")`。 - 示例代码(引用): ```java LocaleList locales = new LocaleList(new Locale(language)); // 创建语言列表 config.setLocales(locales); // 更新配置的语言设置 config.userSetLocale = true; // 标记为用户设置 ``` 3. **调用系统服务更新持久化配置** 通过IActivityManager接口调用`updatePersistentConfiguration`方法,将新配置应用到系统。这需要系统权限,通常在自定义服务或系统APP中实现。ActivityManagerService(AMS)或ActivityTaskManagerService(ATMS)处理此请求,并持久化存储到系统设置。 - 为什么需要:该方法触发系统级配置更新,并确保语言设置被保存(例如,到`/data/system/users/0/settings_system.xml`)。 - 示例代码(引用[^2]): ```java try { IActivityManager am = ActivityManager.getService(); // 获取ActivityManager服务 am.updatePersistentConfiguration(config); // 更新系统配置 BackupManager.dataChanged("com.android.providers.settings"); // 通知设置提供者备份数据 } catch (Exception e) { e.printStackTrace(); } ``` 4. **系统广播配置变化** 更新配置后,系统自动发送`ACTION_CONFIGURATION_CHANGED`广播。所有注册的应用会收到此广播,触发其更新界面(如重新加载资源)。Framework层处理此过程,无需额外代码[^1]。 5. **处理系统级持久化** 语言设置被保存到系统数据库(通过SettingsProvider),确保设备重启后设置生效。引用中通过`BackupManager.dataChanged()`确保设置备份。 ### 应用级适配步骤 系统语言切换后,应用需要响应配置变化。默认情况下,系统会重启应用(Activity重建),但可通过manifest配置避免重启,实现无缝切换(基于引用[^3]和): 1. **在AndroidManifest.xml中声明配置变化处理** 为Activity添加`android:configChanges`属性,指定处理语言(locale)和布局方向(layoutDirection)变化,避免系统重启Activity。 - 示例(引用): ```xml <activity android:name=".MainActivity" android:configChanges="locale|layoutDirection"> ``` 2. **在应用中覆盖onConfigurationChanged方法** 当配置变化发生时,应用在此方法中手动更新界面资源(如字符串)。 - 示例代码: ```java @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // 重新加载语言资源 Resources resources = getResources(); Configuration config = resources.getConfiguration(); config.setLocale(new Locale("zh")); // 设置新语言 resources.updateConfiguration(config, resources.getDisplayMetrics()); // 更新UI,例如重新设置文本 textView.setText(R.string.app_name); } ``` 3. **持久化应用级语言设置(可选)** 如果应用需要记住用户选择(而不是跟随系统),可以使用SharedPreferences保存语言偏好(引用)。 - 示例代码(引用[^4]): ```java // 保存到SharedPreferences SPUtil.put(Constant.CURRENT_LANGUAGE, language); SPUtil.put(Constant.CURRENT_COUNTRY, country); ``` ### 完整流程总结 1. **系统流程**:获取配置 → 设置新Locale → 调用updatePersistentConfiguration → 系统广播变化 → 持久化存储。 2. **应用级流程**:声明configChanges → 处理onConfigurationChanged → 更新UI资源(可选持久化)。 此流程Android 11.0和12.0中类似,但核心类可能略有差异(例如,ActivityTaskManagerService在Android 10+中取代部分AMS功能)[^2]。实现时需注意权限问题(系统APP或root权限),普通应用无法直接调用`updatePersistentConfiguration`。 ### 代码示例(系统服务端,基于引用) 以下是一个简化的自定义服务接口,用于触发系统语言切换: ```java public class LanguageService { public void setSystemLanguage(Context ctx, String language) { if (!TextUtils.isEmpty(language)) { Configuration config = ctx.getResources().getConfiguration(); LocaleList locales = new LocaleList(new Locale(language)); config.setLocales(locales); config.userSetLocale = true; try { IActivityManager am = ActivityManager.getService(); am.updatePersistentConfiguration(config); BackupManager.dataChanged("com.android.providers.settings"); } catch (Exception e) { e.printStackTrace(); } } } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值