Android-语言设置流程分析
Android手机语言切换行为,是通过设置-语言和输入法-语言来改变手机的语言,其实这个功能很少被用户使用。
![](https://code.csdn.net/assets/CODE_ico.png)
- addPreferencesFromResource(R.xml.language_settings);
![](https://code.csdn.net/assets/CODE_ico.png)
- <PreferenceScreen
- android:key="phone_language"
- android:title="@string/phone_language"
- android:fragment="com.android.settings.LocalePicker"
- />
![](https://code.csdn.net/assets/CODE_ico.png)
- @Override
- public View onCreateView(
- LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final View view = super.onCreateView(inflater, container, savedInstanceState);
- final ListView list = (ListView) view.findViewById(android.R.id.list);
- Utils.forcePrepareCustomPreferencesList(container, view, list, false);
- return view;
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- /**
- * Constructs an Adapter object containing Locale information. Content is sorted by
- * {@link LocaleInfo#label}.
- */
- public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) {
- return constructAdapter(context, R.layout.locale_picker_item, R.id.locale);
- }
- public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
- final int layoutId, final int fieldId) {
- boolean isInDeveloperMode = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
- //获取系统支持语言的信息
- final List<LocaleInfo> localeInfos = getAllAssetLocales(context, isInDeveloperMode);
- final LayoutInflater inflater =
- (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos) {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View view;
- TextView text;
- if (convertView == null) {
- view = inflater.inflate(layoutId, parent, false);
- text = (TextView) view.findViewById(fieldId);
- view.setTag(text);
- } else {
- view = convertView;
- text = (TextView) view.getTag();
- }
- LocaleInfo item = getItem(position);
- text.setText(item.toString());
- text.setTextLocale(item.getLocale());
- return view;
- }
- };
- }
而此方法通过getAllAssetLocales()方法获取系统支持语言的信息:
![](https://code.csdn.net/assets/CODE_ico.png)
- public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) {
- final Resources resources = context.getResources();
- //获取系统所支持的语言
- final String[] locales = Resources.getSystem().getAssets().getLocales();
- List<String> localeList = new ArrayList<String>(locales.length);
- Collections.addAll(localeList, locales);
- // Don't show the pseudolocales unless we're in developer mode.
- if (!isInDeveloperMode) {
- localeList.remove("ar-XB");
- localeList.remove("en-XA");
- }
- Collections.sort(localeList);
- final String[] specialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
- final String[] specialLocaleNames = resources.getStringArray(R.array.special_locale_names);
- final ArrayList<LocaleInfo> localeInfos = new ArrayList<LocaleInfo>(localeList.size());
- for (String locale : localeList) {
- final Locale l = Locale.forLanguageTag(locale.replace('_', '-'));
- if (l == null || "und".equals(l.getLanguage())
- || l.getLanguage().isEmpty() || l.getCountry().isEmpty()) {
- continue;
- }
- if (localeInfos.isEmpty()) {
- if (DEBUG) {
- Log.v(TAG, "adding initial "+ toTitleCase(l.getDisplayLanguage(l)));
- }
- localeInfos.add(new LocaleInfo(toTitleCase(l.getDisplayLanguage(l)), l));
- } else {
- // check previous entry:
- // same lang and a country -> upgrade to full name and
- // insert ours with full name
- // diff lang -> insert ours with lang-only name
- final LocaleInfo previous = localeInfos.get(localeInfos.size() - 1);
- if (previous.locale.getLanguage().equals(l.getLanguage()) &&
- !previous.locale.getLanguage().equals("zz")) {
- if (DEBUG) {
- Log.v(TAG, "backing up and fixing " + previous.label + " to " +
- getDisplayName(previous.locale, specialLocaleCodes, specialLocaleNames));
- }
- previous.label = toTitleCase(getDisplayName(
- previous.locale, specialLocaleCodes, specialLocaleNames));
- if (DEBUG) {
- Log.v(TAG, " and adding "+ toTitleCase(
- getDisplayName(l, specialLocaleCodes, specialLocaleNames)));
- }
- localeInfos.add(new LocaleInfo(toTitleCase(
- getDisplayName(l, specialLocaleCodes, specialLocaleNames)), l));
- } else {
- String displayName = toTitleCase(l.getDisplayLanguage(l));
- if (DEBUG) {
- Log.v(TAG, "adding "+displayName);
- }
- localeInfos.add(new LocaleInfo(displayName, l));
- }
- }
- }
- Collections.sort(localeInfos);
- return localeInfos;
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- /**
- * Get the locales that this asset manager contains data for.
- *
- * <p>On SDK 21 (Android 5.0: Lollipop) and above, Locale strings are valid
- * <a href="https://tools.ietf.org/html/bcp47">BCP-47</a> language tags and can be
- * parsed using {@link java.util.Locale#forLanguageTag(String)}.
- *
- * <p>On SDK 20 (Android 4.4W: Kitkat for watches) and below, locale strings
- * are of the form {@code ll_CC} where {@code ll} is a two letter language code,
- * and {@code CC} is a two letter country code.
- */
- public native final String[] getLocales();
![](https://code.csdn.net/assets/CODE_ico.png)
- static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
- {
- Vector<String8> locales;
- AssetManager* am = assetManagerForJavaObject(env, clazz);
- if (am == NULL) {
- return NULL;
- }
- am->getLocales(&locales);
- const int N = locales.size();
- jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
- if (result == NULL) {
- return NULL;
- }
- for (int i=0; i<N; i++) {
- jstring str = env->NewStringUTF(locales[i].string());
- if (str == NULL) {
- return NULL;
- }
- env->SetObjectArrayElement(result, i, str);
- env->DeleteLocalRef(str);
- }
- return result;
- }
通过上面初步的分析,语言的List界面就基本出来了,在getAllAssetLocales()方法中打了个断点,查看了下locales被赋值以后的值:
![](/assets/blank.gif)
![](https://code.csdn.net/assets/CODE_ico.png)
- public static interface LocaleSelectionListener {
- // You can add any argument if you really need it...
- public void onLocaleSelected(Locale locale);
- }
- @Override
- public void onLocaleSelected(final Locale locale) {
- if (Utils.hasMultipleUsers(getActivity())) {
- mTargetLocale = locale;
- showDialog(DLG_SHOW_GLOBAL_WARNING);
- } else {
- getActivity().onBackPressed();
- LocalePicker.updateLocale(locale);
- }
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- /**
- * Requests the system to update the system locale. Note that the system looks halted
- * for a while during the Locale migration, so the caller need to take care of it.
- */
- public static void updateLocale(Locale locale) {
- try {
- IActivityManager am = ActivityManagerNative.getDefault();
- Configuration config = am.getConfiguration();
- // Will set userSetLocale to indicate this isn't some passing default - the user
- // wants this remembered
- config.setLocale(locale);
- am.updateConfiguration(config);
- // Trigger the dirty bit for the Settings Provider.
- BackupManager.dataChanged("com.android.providers.settings");
- } catch (RemoteException e) {
- // Intentionally left blank
- }
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- public void updateConfiguration(Configuration values) {
- enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
- "updateConfiguration()");
- synchronized(this) {
- if (values == null && mWindowManager != null) {
- // sentinel: fetch the current configuration from the window manager
- values = mWindowManager.computeNewConfiguration();
- }
- if (mWindowManager != null) {
- mProcessList.applyDisplaySize(mWindowManager);
- }
- final long origId = Binder.clearCallingIdentity();
- if (values != null) {
- Settings.System.clearConfiguration(values);
- }
- updateConfigurationLocked(values, null, false, false);
- Binder.restoreCallingIdentity(origId);
- }
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- /**
- * @hide Erase the fields in the Configuration that should be applied
- * by the settings.
- */
- public static void clearConfiguration(Configuration inoutConfig) {
- inoutConfig.fontScale = 0;
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- /**
- * Do either or both things: (1) change the current configuration, and (2)
- * make sure the given activity is running with the (now) current
- * configuration. Returns true if the activity has been left running, or
- * false if <var>starting</var> is being destroyed to match the new
- * configuration.
- * @param persistent TODO
- */
- boolean updateConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean persistent, boolean initLocale) {
- int changes = 0;
- if (values != null) {
- Configuration newConfig = new Configuration(mConfiguration);
- changes = newConfig.updateFrom(values);
- if (changes != 0) {
- if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
- Slog.i(TAG, "Updating configuration to: " + values);
- }
- EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
- if (values.locale != null && !initLocale) {
- saveLocaleLocked(values.locale,
- !values.locale.equals(mConfiguration.locale),
- values.userSetLocale);
- }
- mConfigurationSeq++;
- if (mConfigurationSeq <= 0) {
- mConfigurationSeq = 1;
- }
- newConfig.seq = mConfigurationSeq;
- mConfiguration = newConfig;
- Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
- mUsageStatsService.reportConfigurationChange(newConfig, mCurrentUserId);
- //mUsageStatsService.noteStartConfig(newConfig);
- final Configuration configCopy = new Configuration(mConfiguration);
- // TODO: If our config changes, should we auto dismiss any currently
- // showing dialogs?
- mShowDialogs = shouldShowDialogs(newConfig);
- AttributeCache ac = AttributeCache.instance();
- if (ac != null) {
- ac.updateConfiguration(configCopy);
- }
- // Make sure all resources in our process are updated
- // right now, so that anyone who is going to retrieve
- // resource values after we return will be sure to get
- // the new ones. This is especially important during
- // boot, where the first config change needs to guarantee
- // all resources have that config before following boot
- // code is executed.
- mSystemThread.applyConfigurationToResources(configCopy);
- if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
- Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
- msg.obj = new Configuration(configCopy);
- mHandler.sendMessage(msg);
- }
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
- try {
- if (app.thread != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
- + app.processName + " new config " + mConfiguration);
- app.thread.scheduleConfigurationChanged(configCopy);
- }
- } catch (Exception e) {
- }
- }
- Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_REPLACE_PENDING
- | Intent.FLAG_RECEIVER_FOREGROUND);
- broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
- null, AppOpsManager.OP_NONE, false, false, MY_PID,
- Process.SYSTEM_UID, UserHandle.USER_ALL);
- if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
- intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
- }
- }
- }
- boolean kept = true;
- final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
- // mainStack is null during startup.
- if (mainStack != null) {
- if (changes != 0 && starting == null) {
- // If the configuration changed, and the caller is not already
- // in the process of starting an activity, then find the top
- // activity to check if its configuration needs to change.
- starting = mainStack.topRunningActivityLocked(null);
- }
- if (starting != null) {
- kept = mainStack.ensureActivityConfigurationLocked(starting, changes);
- // And we need to make sure at this point that all other activities
- // are made visible with the correct configuration.
- mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
- }
- }
- if (values != null && mWindowManager != null) {
- mWindowManager.setNewConfiguration(mConfiguration);
- }
- return kept;
- }
此方法主要做两件事:第一,改变当前的configuration,将新的数据放进去。第二,保证正在运行的应用程序界面更新最新的configuration。先调用updateFrom()方法,遍历configuration包含的属性是否改变,如果有改变就返回一个对应的整数,如果没有改变就返回0。就语言改变而言,根据上面的分析,configuration至少有3个属性发生了改变:fontscale(之前没有设置字体的效果就不会改变)、locale和布局的direction。
![](https://code.csdn.net/assets/CODE_ico.png)
- /**
- * Save the locale. You must be inside a synchronized (this) block.
- */
- private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
- if(isDiff) {
- SystemProperties.set("user.language", l.getLanguage());
- SystemProperties.set("user.region", l.getCountry());
- }
- if(isPersist) {
- SystemProperties.set("persist.sys.language", l.getLanguage());
- SystemProperties.set("persist.sys.country", l.getCountry());
- SystemProperties.set("persist.sys.localevar", l.getVariant());
- mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG, l));
- }
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
- Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
- msg.obj = new Configuration(configCopy);
- mHandler.sendMessage(msg);
- }
- ...
- case UPDATE_CONFIGURATION_MSG: {
- final ContentResolver resolver = mContext.getContentResolver();
- Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
- } break;
![](https://code.csdn.net/assets/CODE_ico.png)
- mSystemThread = ActivityThread.currentActivityThread();
![](https://code.csdn.net/assets/CODE_ico.png)
- //此方法属于ActivityThread
- public final void applyConfigurationToResources(Configuration config) {
- synchronized (mResourcesManager) {
- mResourcesManager.applyConfigurationToResourcesLocked(config, null);
- }
- }
- //此方法属于ResourcesManage
- public final boolean applyConfigurationToResourcesLocked(Configuration config,
- CompatibilityInfo compat) {
- if (mResConfiguration == null) {
- mResConfiguration = new Configuration();
- }
- if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
- + mResConfiguration.seq + ", newSeq=" + config.seq);
- return false;
- }
- int changes = mResConfiguration.updateFrom(config);
- flushDisplayMetricsLocked();
- DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
- if (compat != null && (mResCompatibilityInfo == null ||
- !mResCompatibilityInfo.equals(compat))) {
- mResCompatibilityInfo = compat;
- changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
- | ActivityInfo.CONFIG_SCREEN_SIZE
- | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
- }
- // set it for java, this also affects newly created Resources
- if (config.locale != null) {
- Locale.setDefault(config.locale);
- }
- Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
- ApplicationPackageManager.configurationChanged();
- //Slog.i(TAG, "Configuration changed in " + currentPackageName());
- Configuration tmpConfig = null;
- for (int i=mActiveResources.size()-1; i>=0; i--) {
- ResourcesKey key = mActiveResources.keyAt(i);
- Resources r = mActiveResources.valueAt(i).get();
- if (r != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
- + r + " config to: " + config);
- int displayId = key.mDisplayId;
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- DisplayMetrics dm = defaultDisplayMetrics;
- final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
- if (!isDefaultDisplay || hasOverrideConfiguration) {
- if (tmpConfig == null) {
- tmpConfig = new Configuration();
- }
- tmpConfig.setTo(config);
- if (!isDefaultDisplay) {
- dm = getDisplayMetricsLocked(displayId);
- applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
- }
- if (hasOverrideConfiguration) {
- tmpConfig.updateFrom(key.mOverrideConfiguration);
- }
- r.updateConfiguration(tmpConfig, dm, compat);
- } else {
- r.updateConfiguration(config, dm, compat);
- }
- //Slog.i(TAG, "Updated app resources " + v.getKey()
- // + " " + r + ": " + r.getConfiguration());
- } else {
- //Slog.i(TAG, "Removing old resources " + v.getKey());
- mActiveResources.removeAt(i);
- }
- }
- return changes != 0;
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord app = mLruProcesses.get(i);
- try {
- if (app.thread != null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
- + app.processName + " new config " + mConfiguration);
- app.thread.scheduleConfigurationChanged(configCopy);
- }
- } catch (Exception e) {
- }
- }
![](/assets/blank.gif)
![](https://code.csdn.net/assets/CODE_ico.png)
- public void scheduleConfigurationChanged(Configuration config) {
- updatePendingConfiguration(config);
- sendMessage(H.CONFIGURATION_CHANGED, config);
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- case CONFIGURATION_CHANGED:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
- mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
- handleConfigurationChanged((Configuration)msg.obj, null);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
![](https://code.csdn.net/assets/CODE_ico.png)
- final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
- int configDiff = 0;
- synchronized (mResourcesManager) {
- if (mPendingConfiguration != null) {
- if (!mPendingConfiguration.isOtherSeqNewer(config)) {
- config = mPendingConfiguration;
- mCurDefaultDisplayDpi = config.densityDpi;
- updateDefaultDensity();
- }
- mPendingConfiguration = null;
- }
- if (config == null) {
- return;
- }
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
- + config);
- mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
- if (mConfiguration == null) {
- mConfiguration = new Configuration();
- }
- if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
- return;
- }
- configDiff = mConfiguration.diff(config);
- mConfiguration.updateFrom(config);
- config = applyCompatConfiguration(mCurDefaultDisplayDpi);
- }
- ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
- freeTextLayoutCachesIfNeeded(configDiff);
- if (callbacks != null) {
- final int N = callbacks.size();
- for (int i=0; i<N; i++) {
- performConfigurationChanged(callbacks.get(i), config);
- }
- }
- }
![](https://code.csdn.net/assets/CODE_ico.png)
- private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {
- // Only for Activity objects, check that they actually call up to their
- // superclass implementation. ComponentCallbacks2 is an interface, so
- // we check the runtime type and act accordingly.
- Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
- if (activity != null) {
- activity.mCalled = false;
- }
- boolean shouldChangeConfig = false;
- if ((activity == null) || (activity.mCurrentConfig == null)) {
- shouldChangeConfig = true;
- } else {
- // If the new config is the same as the config this Activity
- // is already running with then don't bother calling
- // onConfigurationChanged
- int diff = activity.mCurrentConfig.diff(config);
- if (diff != 0) {
- // If this activity doesn't handle any of the config changes
- // then don't bother calling onConfigurationChanged as we're
- // going to destroy it.
- if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
- shouldChangeConfig = true;
- }
- }
- }
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
- + ": shouldChangeConfig=" + shouldChangeConfig);
- if (shouldChangeConfig) {
- cb.onConfigurationChanged(config);
- if (activity != null) {
- if (!activity.mCalled) {
- throw new SuperNotCalledException(
- "Activity " + activity.getLocalClassName() +
- " did not call through to super.onConfigurationChanged()");
- }
- activity.mConfigChangeFlags = 0;
- activity.mCurrentConfig = new Configuration(config);
- }
- }
- }
转载于:https://www.cnblogs.com/Free-Thinker/p/5461523.html
Android-语言设置流程分析相关推荐
- Android 7.1.2 默认输入法的设置流程分析与修改
一.默认输入法的设置流程分析 设置流程分析 1. Android系统开机后,当ActivityManagerService及PackageManagerService都ready后,systemse ...
- android camera2 API流程分析
Android camera2 API流程分析 Android5.0之后,新推出来了一个类,android.hardware.camera2,与原来的camera的类实现照相和拍视频的流程有所不同,原 ...
- Android UI绘制流程分析(三)measure
源码版本Android 6.0 请参阅:http://androidxref.com/6.0.1_r10 本文目的是分析从Activity启动到走完绘制流程并显示在界面上的过程,在源码展示阶段为了使跟 ...
- Android -- Wifi启动流程分析
Android -- Wifi启动流程分析 Android网络各个模式中,Wifi应该是目前最常用的一种网络方式了:下面就简单介绍下Android中Wifi的启动流程. 当我在Setting菜单里点击 ...
- Android SDCard UnMounted 流程分析(三)
前篇地址 Android SDCard UnMounted 流程分析(一) Android SDCard UnMounted 流程分析(二) 前一篇讲到SDCard unmout onEvent 发送 ...
- 【SemiDrive源码分析】【X9芯片启动流程】27 - AP1 Android Preloader启动流程分析(加载atf、tos、bootloader镜像后进入BL31环境)
[SemiDrive源码分析][X9芯片启动流程]27 - AP1 Android Preloader启动流程分析(加载atf.tos.bootloader镜像后进入BL31环境) 一.Android ...
- android 铃声设置流程讲解
总体思路为 : 1.截取铃声 2.保存入sd卡 3.获取铃声信息 4.将信息和文件路径写入数据库获得铃声Uri 5.将获得的Uri设置为铃声. 核心实现:在 public class DefaultR ...
- android 恢复出厂设置流程分析,基于Android系统快速恢复出厂设置方法实现.doc
基于Android系统快速恢复出厂设置方法实现 基于Android系统快速恢复出厂设置方法实现 摘 要:针对使用Android系统的智能电视进行恢复出厂设置时重置速度慢的情况进行了研究和分析,从其重置 ...
- Android 音量控制流程分析
在Android平台上,音量键,主页键(home),都是全局按键,但是主页键是个例外不能被应用所捕获.下面分析一下音量按键的流程,主要从framework层处理开始,至于 EventHub 从驱动的/ ...
最新文章
- 【BZOJ 4016】[FJOI2014]最短路径树问题
- Django 开发中的最佳实践之一
- 电子工程可以报考二建_电子科学与技术专业能报考二级建造师吗?
- DataGridView中回车键的妙用
- Java多线程之synchronized(二)
- pytorch学习知识点总结
- 经典C语言程序100例之四一
- ACM练习 校赛83C:纸片儿(测试用例通过但WA/TLE)
- 牛人主页(主页有很多论文代码)【真的好强大】
- python数字转字符串_python如何将字符转换为数字
- ubuntu安装minisat_minisat 安装指南
- TCP/IP网络编程(2)
- java 中的流_深入理解Java中的流(Stream)
- IDEA中控制台中文乱码问题
- zookeeper集群搭建和API使用
- java 定义接口school_Java接口介绍
- python3字典详解_Python3实现的字典遍历操作详解
- 斐波那契数列的三种解法
- Android 触摸事件转换为鼠标事件
- 计算机组成和体系结构-Flynn分类法
热门文章
- matlab的diray在哪,matlab笔记
- 2020计算机网络基础与应用,2020年国防科技大学硕士研究生考试F1107计算机网络基础考试大纲...
- java培训就是害人的_[Java教程]粗心害死人啊,我的天。
- char qt 转unicode_Qt QString 中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码与转码问题...
- leetcode31. 下一个排列
- 关系数据库——mysql常用函数总结
- C语言: ---Linux下ulimit是什么鬼
- 泛型lua的for循环以及lua的特殊的dowhile循环
- 无限踩坑系列(4)-远程登入服务器
- java图形用户登录界面_Java简单登录图形界面