一、关闭媒体音量睡眠模式中关闭媒体音量但是在我们自己的设置中依然可以调节音量但是调节后会自动恢复静音。先看下原生设置的调用逻辑。//Settings/src/com/android/settings/notification/modes/ZenModeOtherPreferenceController.java Override public boolean onPreferenceChange(Preference preference, Object newValue) { final boolean allow (Boolean) newValue; return savePolicy(policy - policy.allowCategory(getCategory(), allow)); } private int getCategory() { switch (getPreferenceKey()) { case modes_category_alarm: return PRIORITY_CATEGORY_ALARMS; case modes_category_media: return PRIORITY_CATEGORY_MEDIA; case modes_category_system: return PRIORITY_CATEGORY_SYSTEM; case modes_category_reminders: return PRIORITY_CATEGORY_REMINDERS; case modes_category_events: return PRIORITY_CATEGORY_EVENTS; } return -1; }ZenModeOtherPreferenceController继承了AbstractZenModePreferenceController。//Settings/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java /** * Subclasses should call this method (or a more specific one, like {link #savePolicy} from * their {code onPreferenceChange()} or similar, in order to apply changes to the mode being * edited (e.g. {code saveMode(mode - { mode.setX(value); return mode; } }. * * param updater Function to update the {link ZenMode}. Modifying and returning the same * instance is ok. */ protected final boolean saveMode(FunctionZenMode, ZenMode updater) { checkState(mBackend ! null); ZenMode mode mZenMode; if (mode null) { Log.wtf(TAG, Cannot save mode, it hasnt been loaded ( getClass() )); return false; } mode updater.apply(mode); mBackend.updateMode(mode); return true; } protected final boolean savePolicy(FunctionZenPolicy.Builder, ZenPolicy.Builder updater) { return saveMode(mode - { ZenPolicy.Builder policyBuilder new ZenPolicy.Builder(mode.getPolicy()); policyBuilder updater.apply(policyBuilder); mode.setPolicy(policyBuilder.build()); return mode; }); }最终调用到了mBackend.updateMode。//frameworks/base/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenModesBackend.java public void updateMode(ZenMode mode) { if (mode.isManualDnd()) { try { NotificationManager.Policy dndPolicy new ZenModeConfig().toNotificationPolicy(mode.getPolicy()); mNotificationManager.setNotificationPolicy(dndPolicy, /* fromUser */ true); mNotificationManager.setManualZenRuleDeviceEffects( mode.getRule().getDeviceEffects()); } catch (Exception e) { Log.w(TAG, Error updating manual mode, e); } } else { mNotificationManager.updateAutomaticZenRule(mode.getId(), mode.getRule(), /* fromUser */ true); } }可以看到是在NotificationManager.setNotificationPolicy这样的话我们就可以在自己的应用里面获取到对应的设置了。private NotificationManager.Policy mPolicy; private final NotificationManager mNotificationManager; mNotificationManager (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE); public boolean isPriorityCategoryEnabled(int categoryType) { updatePolicy(); return (mPolicy.priorityCategories categoryType) ! 0; } public void updatePolicy() { if (mNotificationManager ! null) { mPolicy mNotificationManager.getNotificationPolicy(); } }在我们需要刷新视图的方法中添加isPriorityCategoryEnabled()就可以控制用户能否调节音量了。二、修改默认的拼写检查工具系统-键盘-拼写检查工具默认是AOSP拼写检查工具我们系统内置了Gboard因此希望默认是Gboard的拼写检查工具。先看下设置中的数据是从哪获取的。//Settings/src/com/android/settings/inputmethod/SpellCheckersSettings.java Override public void onCreate(final Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.spellchecker_prefs); mSpellCheckerLanaguagePref findPreference(KEY_SPELL_CHECKER_LANGUAGE); mTsm (TextServicesManager) getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); mCurrentSci mTsm.getCurrentSpellChecker(); mEnabledScis mTsm.getEnabledSpellCheckers(); populatePreferenceScreen(); }//frameworks/base/services/core/java/com/android/server/textservices/TextServicesManagerService.java private static class TextServicesData { ... NonNull private String getSelectedSpellChecker() { return getString(Settings.Secure.SELECTED_SPELL_CHECKER, ); } Nullable public SpellCheckerInfo getCurrentSpellChecker() { final String curSpellCheckerId getSelectedSpellChecker(); if (TextUtils.isEmpty(curSpellCheckerId)) { return null; } return mSpellCheckerMap.get(curSpellCheckerId); } ... }由于SELECTED_SPELL_CHECKER没有配置默认值service中返回的是null但实际上进入系统还是选中了AOSP的选项的那应该是有初始化配置加载了默认选项。//frameworks/base/services/core/java/com/android/server/textservices/TextServicesManagerService.java GuardedBy(mLock) private void initializeInternalStateLocked(UserIdInt int userId) { TextServicesData tsd mUserData.get(userId); if (tsd null) { tsd new TextServicesData(userId, mContext); mUserData.put(userId, tsd); } tsd.initializeTextServicesData(); SpellCheckerInfo sci tsd.getCurrentSpellChecker(); if (sci null) { sci findAvailSystemSpellCheckerLocked(null, tsd); // Set the current spell checker if there is one or more system spell checkers // available. In this case, sci is the first one in the available spell // checkers. setCurrentSpellCheckerLocked(sci, tsd); } } private SpellCheckerInfo findAvailSystemSpellCheckerLocked(String prefPackage, TextServicesData tsd) { // Filter the spell checker list to remove spell checker services that are not pre-installed ArrayListSpellCheckerInfo spellCheckerList new ArrayList(); for (SpellCheckerInfo sci : tsd.mSpellCheckerList) { if ((sci.getServiceInfo().applicationInfo.flags ApplicationInfo.FLAG_SYSTEM) ! 0) { spellCheckerList.add(sci); } } final int spellCheckersCount spellCheckerList.size(); if (spellCheckersCount 0) { Slog.w(TAG, no available spell checker services found); return null; } if (prefPackage ! null) { for (int i 0; i spellCheckersCount; i) { final SpellCheckerInfo sci spellCheckerList.get(i); if (prefPackage.equals(sci.getPackageName())) { if (DBG) { Slog.d(TAG, findAvailSystemSpellCheckerLocked: sci.getPackageName()); } return sci; } } } // Look up a spell checker based on the system locale. // TODO: Still there is a room to improve in the following logic: e.g., check if the package // is pre-installed or not. final Locale systemLocal mContext.getResources().getConfiguration().locale; final ArrayListLocale suitableLocales LocaleUtils.getSuitableLocalesForSpellChecker(systemLocal); if (DBG) { Slog.w(TAG, findAvailSystemSpellCheckerLocked suitableLocales Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()]))); } final int localeCount suitableLocales.size(); for (int localeIndex 0; localeIndex localeCount; localeIndex) { final Locale locale suitableLocales.get(localeIndex); for (int spellCheckersIndex 0; spellCheckersIndex spellCheckersCount; spellCheckersIndex) { final SpellCheckerInfo info spellCheckerList.get(spellCheckersIndex); final int subtypeCount info.getSubtypeCount(); for (int subtypeIndex 0; subtypeIndex subtypeCount; subtypeIndex) { final SpellCheckerSubtype subtype info.getSubtypeAt(subtypeIndex); final Locale subtypeLocale SubtypeLocaleUtils.constructLocaleFromString( subtype.getLocale()); if (locale.equals(subtypeLocale)) { // TODO: We may have more spell checkers that fall into this category. // Ideally we should pick up the most suitable one instead of simply // returning the first found one. return info; } } } } if (spellCheckersCount 1) { Slog.w(TAG, more than one spell checker service found, picking first); } return spellCheckerList.get(0); }在初始化方法中看到当返回null是会去查找可用的拼写检查工具并返回列表中的第一个值。现象分析完毕可以开始进行修改了要么在查找可用拼写工具时设置优先排序将Gboard放在第一个要么配置默认选中值SELECTED_SPELL_CHECKER。这里为了方便我直接配置了默认值。//frameworks/base/packages/SettingsProvider/res/values/defaults.xml string namedef_spell_checker translatablefalse com.google.android.inputmethod.latin/com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService /string//frameworks/base/packages/SettingsProvider/src/com/android/provider/settings/DatabaseHelper.java private void loadSecureSettings(SQLiteDatabase db) { ... loadStringSetting(stmt, Settings.Secure.SELECTED_SPELL_CHECKER, R.string.def_spell_checker); ... }三、隐藏应用列表中的部分应用有些我们自己的系统应用不想让用户看到需要隐藏。原生设置中有两个区域显示应用一个是最近使用的应用一个是全部应用都需要进行隐藏。最近使用应用中已经有一个隐藏的逻辑了直接在对应位置添加应用包名即可。// packages/apps/Settings/src/com/android/settings/applications/RecentAppStatsMixin.java public class RecentAppStatsMixin implements LifecycleObserver, OnStart { private static final String TAG RecentAppStatsMixin; private static final SetString SKIP_SYSTEM_PACKAGES new ArraySet(); VisibleForTesting ListUsageStatsWrapper mRecentApps; private final int mMaximumApps; private final Context mContext; private final PackageManager mPm; private final UserManager mUserManager; private final PowerManager mPowerManager; private final ApplicationsState mApplicationsState; private final ListRecentAppStatsListener mAppStatsListeners; private Calendar mCalendar; static { SKIP_SYSTEM_PACKAGES.addAll(Arrays.asList( android, com.android.phone, SETTINGS_PACKAGE_NAME, SYSTEMUI_PACKAGE_NAME, com.android.providers.calendar, com.android.providers.media, com.your.package.name )); }所有应用显示的逻辑中有一个filter在里面叠加一个我们的包名过滤就可以实现隐藏了。//packages/apps/Settings/src/com/android/settings/spa/app/AllAppList.kt val hiddenPackages setOf( com.your.package.name, ... com.your.package.name2 ) override fun filter( userIdFlow: FlowInt, option: Int, recordListFlow: FlowListAppRecordWithSize, ): FlowListAppRecordWithSize recordListFlow.filterItem { record - // 原有筛选条件 val baseMatch when (SpinnerItem.entries.getOrNull(option)) { SpinnerItem.Enabled - record.app.enabled !record.app.isInstantApp SpinnerItem.Disabled - isDisabled(record) SpinnerItem.Instant - isInstant(record) else - true } // 叠加包名过滤 val packageMatch record.app.packageName !in hiddenPackages baseMatch packageMatch }四、配置默认浏览器在frameworks/base/core/res/res/values/config.xml中可以配置默认浏览器在对应标签中填入想要默认的浏览器包名即可。string namedefault_browser translatablefalsecom.android.chrome/string五、Launcher3中长按应用图标时图标会消失松手后恢复显示这个问题比较奇怪逻辑上都是原生的不知道为什么要让图标消失但是在最新的android16Launcher3上又没有这个问题现象了。这里不分析具体的流程了可能最新上的又有变化感兴趣的可以自己去看下直接贴上修改代码。//packages/apps/Launcher3/src/com/android/launcher3/popup/PopupContainerWithArrow.java /** * Determines when the deferred drag should be started. * * Current behavior: * - Start the drag if the touch passes a certain distance from the original touch down. */ public DragOptions.PreDragCondition createPreDragCondition(boolean updateIconUi) { return new DragOptions.PreDragCondition() { Override public boolean shouldStartDrag(double distanceDragged) { return distanceDragged mStartDragThreshold; } Override public void onPreDragStart(DropTarget.DragObject dragObject) { if (!updateIconUi) { return; } // 这里注释掉控制显示的逻辑 if (mIsAboveIcon) { // Hide only the icon, keep the text visible. //mOriginalIcon.setIconVisible(false); //mOriginalIcon.setVisibility(VISIBLE); } else { // Hide both the icon and text. //mOriginalIcon.setVisibility(INVISIBLE); } } Override public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) { if (!updateIconUi) { return; } mOriginalIcon.setIconVisible(true); if (dragStarted) { // Make sure we keep the original icon hidden while it is being dragged. mOriginalIcon.setVisibility(INVISIBLE); } else { // TODO: add WW logging if want to add logging for long press on popup // container. // mLauncher.getUserEventDispatcher().logDeepShortcutsOpen(mOriginalIcon); if (!mIsAboveIcon) { // Show the icon but keep the text hidden. mOriginalIcon.setVisibility(VISIBLE); mOriginalIcon.setTextVisibility(false); } } } }; }//packages/apps/Launcher3/src/com/android/launcher3/Workspace.java public void startDrag(CellInfo cellInfo, DragOptions options) { View child cellInfo.cell; mDragInfo cellInfo; // 判断是应用图标时不再进行隐藏 if (!(child instanceof BubbleTextView)) { child.setVisibility(INVISIBLE); } if (options.isAccessibleDrag) { mAccessibilityDragListener new AccessibleDragListenerAdapter(this, WorkspaceAccessibilityHelper::new) { Override protected void enableAccessibleDrag(boolean enable, Nullable DragObject dragObject) { super.enableAccessibleDrag(enable, dragObject); setEnableForLayout(mLauncher.getHotseat(), enable); if (enable dragObject ! null dragObject.dragInfo instanceof LauncherAppWidgetInfo) { mLauncher.getHotseat().setImportantForAccessibility( IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } } }; } beginDragShared(child, this, options); }
企业数字化 ERP 产品动态
相关推荐
WebBatchRequest 安装、使用教程 小记: ****进行子域名信息收集 发现了1k域名 这么多我可不会一个一个去请求吧 这太浪费时间了 所以就去找了这个工具****
介绍:
WebBatchRequest(Web批量请求器)是一款**轻量级的批量 HTTP 请求工具**,主要用于安全… · 2026/9/24 16:56:35
palera1n 越狱工具安装指南:A8–A11 老设备 iOS 15 以上怎么越狱 palera1n 越狱工具安装指南:A8–A11 老设备 iOS 15 以上怎么越狱 【免费下载链接】palera1n Jailbreak for A8 through A11, T2 devices, on iOS/iPadOS/tvOS 15.0, bridgeOS 5.0 and higher. 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n
pa… · 2026/9/24 16:56:35
【股票交易】第 49 章 移动平均线与趋势跟踪 回到目录文章目录49.1 移动平均线是什么简单移动平均线:不断更新的价格平均数股价下跌,均线为什么仍然上涨指数移动平均线 :给近期价格更高权重49.2 移动平均线有什么用途为趋势观察提供一致的参照周期选择决定观察尺度衡量价格偏离近期平均水… · 2026/9/24 17:27:07
lu,震惊分析实验系统、震惊实验视频分析系统 震惊反射系统用于分析动物受到突发强刺激后的应激行为,单台计算机可管控 1‑5 个震惊反应箱。除噪声刺激外,还可叠加光、电、气流组合刺激,刺激间隔技术参数1、重量传感器量程:1‑2kg 2、系统架构:主控制器搭配装置控制… · 2026/9/24 17:27:07
2026 大幅面数码印刷设备行业观察:国产压电写真机技术演进与设备选型参考 本文面向广告加工、图文印刷行业从业者,梳理 2026 大幅面数码印刷设备的技术现状,包含压电写真、UV 打印技术拆解,以及工厂设备选型参考。
摘要:随着个性化小批量订单持续释放需求,国内大幅面数码印刷设备行业保持稳步… · 2026/9/24 17:27:07
用思维赚钱14:求财与财富观的境界 天下熙熙皆为利来,天下攘攘皆为利往。在这个世界上,芸芸众生,追求经济利益或者说求财,在一定程度上,可以说具有普遍性。追求权色名利,就一般意义上讲,并没有天然的是非对错,都是可以… · 2026/9/24 17:27:07
双向RNN 如果不加特别说明,RNN的计算一般是从左到右的,即第t步的特征计算只能“看到”的信息,但从语义理解的角度来看,有时只看前边时间步的信息是不够的。我们来看下边的例子。南京市 长江 大桥 是 一个 工程 奇迹。
南京 市长 江大桥 是… · 2026/9/24 17:27:07
【股票交易】专栏介绍 为什么同一家公司的经营状况没有明显变化,股价却可能上涨或下跌 30%?
因为股价不仅反映公司当下的经营结果,还包含市场对未来增长、资金成本和风险的判断。同样的利润,在不同的经济环境、行业阶段和市场情绪下,可能对… · 2026/9/24 17:26:48
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44