<!-- Interruptions --> <com.android.settingslib.RestrictedPReference android:key="zen_mode" android:title="@string/zen_mode_settings_title" settings:useAdminDisabledSummary="true" settings:keyWords="@string/keywords_sounds_and_notifications_interruptions" android:fragment="com.android.settings.notification.ZenModeSettings" />点击勿扰选项进入ZenModeSettings中。ZenModeSettings中的布局文件为zen_mode_settings,如下:Settings/res/xml/zen_mode_settings.xml<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:key="zen_mode_settings" android:title="@string/zen_mode_settings_title" > <!-- Priority only allows --> <PreferenceScreen android:key="priority_settings" android:title="@string/zen_mode_priority_settings_title" android:fragment="com.android.settings.notification.ZenModePrioritySettings" /> <!-- Automated rules --> <PreferenceScreen android:key="automation_settings" android:title="@string/zen_mode_automation_settings_title" android:fragment="com.android.settings.notification.ZenModeAutomationSettings" /> <!-- Visual interruptions --> <PreferenceScreen android:key="visual_interruptions_settings" android:title="@string/zen_mode_visual_interruptions_settings_title" android:fragment="com.android.settings.notification.ZenModeVisualInterruptionSettings" /></PreferenceScreen>上面的布局文件和我们从手机上看到的勿扰设置界面一样。我们可以看出ZenModePrioritySettings 、ZenModeAutomationSettings 、ZenModeVisualInterruptionSettings分别对应着仅允许优先打扰内容、自动规则、屏蔽视觉打扰三种页面。
ZenModeSettings、ZenModePrioritySettings、ZenModeAutomationSettings 、ZenModeVisualInterruptionSettings都继承于ZenModeSettingsBase。我们来分别看一下这些类。
ZenModeSettings这个类,我们从代码中可以看出它只是三项设置界面的入口,以及对勿扰的更新做一些界面的显示工作。如下代码:
Settings/src/com/android/settings/notification/ZenModeSettings.java
@Override protected void onZenModeChanged() { updateControls(); } @Override protected void onZenModeConfigChanged() { mPolicy = NotificationManager.from(mContext).getNotificationPolicy(); updateControls(); } private void updateControls() { updatePrioritySettingsSummary(); updateVisualSettingsSummary(); } private void updatePrioritySettingsSummary() { String s = getResources().getString(R.string.zen_mode_alarms); s = appendLowercase(s, isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_REMINDERS), R.string.zen_mode_reminders); s = appendLowercase(s, isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_EVENTS), R.string.zen_mode_events); if (isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_MESSAGES)) { if (mPolicy.priorityMessageSenders == Policy.PRIORITY_SENDERS_ANY) { s = appendLowercase(s, true, R.string.zen_mode_all_messages); } else { s = appendLowercase(s, true, R.string.zen_mode_selected_messages); } } if (isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_CALLS)) { if (mPolicy.priorityCallSenders == Policy.PRIORITY_SENDERS_ANY) { s = appendLowercase(s, true, R.string.zen_mode_all_callers); } else { s = appendLowercase(s, true, R.string.zen_mode_selected_callers); } } else if (isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_REPEAT_CALLERS)) { s = appendLowercase(s, true, R.string.zen_mode_repeat_callers); } mPrioritySettings.setSummary(s); } private void updateVisualSettingsSummary() { String s = getString(R.string.zen_mode_all_visual_interruptions); if (isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_ON) && isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF)) { s = getString(R.string.zen_mode_no_visual_interruptions); } else if (isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_ON)) { s = getString(R.string.zen_mode_screen_on_visual_interruptions); } else if (isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF)) { s = getString(R.string.zen_mode_screen_off_visual_interruptions); } mVisualSettings.setSummary(s); }我们再看ZenModePrioritySettings类,首先它负责自定义优先打扰的内容,其中包括闹钟、提醒、活动、消息、通话(仅限来自联系人)、重复来电者(如果同一个人在15分钟内第二次来电,则允许显示通知)。这面也仅是一些开关,将最后的更改用NotificationManager.from(mContext).setNotificationPolicy(mPolicy);进行保存,其中也只有消息和通话需要选择,我们来看一下通话的设置以及保存,其余的类似:Settings/src/com/android/settings/notification/ZenModePrioritySettings.java
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.zen_mode_priority_settings); final PreferenceScreen root = getPreferenceScreen(); mPolicy = NotificationManager.from(mContext).getNotificationPolicy(); ... mCalls = (DropDownPreference) root.findPreference(KEY_CALLS); addSources(mCalls); mCalls.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (mDisableListeners) return false; final int val = Integer.parseInt((String) newValue); final boolean allowCalls = val != SOURCE_NONE; final int allowCallsFrom = val == SOURCE_NONE ? mPolicy.priorityCallSenders : val; MetricsLogger.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_CALLS, val); if (DEBUG) Log.d(TAG, "onPrefChange allowCalls=" + allowCalls + " allowCallsFrom=" + ZenModeConfig.sourceToString(allowCallsFrom)); savePolicy(getNewPriorityCategories(allowCalls, Policy.PRIORITY_CATEGORY_CALLS), allowCallsFrom, mPolicy.priorityMessageSenders, mPolicy.suppressedVisualEffects); return true; } }); ... updateControls(); } private void updateControls() { mDisableListeners = true; if (mCalls != null) { mCalls.setValue(Integer.toString( isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS) ? mPolicy.priorityCallSenders : SOURCE_NONE)); } mMessages.setValue(Integer.toString( isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_MESSAGES) ? mPolicy.priorityMessageSenders : SOURCE_NONE)); mReminders.setChecked(isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REMINDERS)); mEvents.setChecked(isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_EVENTS)); mRepeatCallers.setChecked( isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS)); mRepeatCallers.setVisible(!isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS) || mPolicy.priorityCallSenders != Policy.PRIORITY_SENDERS_ANY); mDisableListeners = false; } private void savePolicy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders, int suppressedVisualEffects) { mPolicy = new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders, suppressedVisualEffects); NotificationManager.from(mContext).setNotificationPolicy(mPolicy); }ZenModeVisualInterruptionSettings和ZenModePrioritySettings类似,只是换成了屏幕开启时屏蔽和屏幕关闭时屏蔽两个开关,所以就不分析了。我们看ZenModeAutomationSettings这个稍微不同的类。
在ZenModeSettingsBase中有一个mRules的集合,存储着用户自己定义的AutomaticZenRule,而mRules的值是NotificationManager中获取的的。也就是这里规则的维护存储也还是在NotificationManager中,如下代码。
Settings/src/com/android/settings/notification/ZenModeSettingsBase.java
abstract public class ZenModeSettingsBase extends RestrictedSettingsFragment { ... protected Context mContext; protected Set<Map.Entry<String, AutomaticZenRule>> mRules; ... private void updateZenMode(boolean fireChanged) { final int zenMode = Settings.Global.getInt(getContentResolver(), Global.ZEN_MODE, mZenMode); if (zenMode == mZenMode) return; mZenMode = zenMode; if (DEBUG) Log.d(TAG, "updateZenMode mZenMode=" + mZenMode); if (fireChanged) { onZenModeChanged(); } } protected String addZenRule(AutomaticZenRule rule) { try { String id = NotificationManager.from(mContext).addAutomaticZenRule(rule); final AutomaticZenRule savedRule = NotificationManager.from(mContext).getAutomaticZenRule(id); maybeRefreshRules(savedRule != null, true); return id; } catch (Exception e) { return null; } } protected boolean setZenRule(String id, AutomaticZenRule rule) { final boolean success = NotificationManager.from(mContext).updateAutomaticZenRule(id, rule); maybeRefreshRules(success, true); return success; } protected boolean removeZenRule(String id) { final boolean success = NotificationManager.from(mContext).removeAutomaticZenRule(id); maybeRefreshRules(success, true); return success; } protected void maybeRefreshRules(boolean success, boolean fireChanged) { if (success) { mRules = getZenModeRules(); if (DEBUG) Log.d(TAG, "Refreshed mRules=" + mRules); if (fireChanged) { onZenModeConfigChanged(); } } } protected void setZenMode(int zenMode, Uri conditionId) { NotificationManager.from(mContext).setZenMode(zenMode, conditionId, TAG); } private Set<Map.Entry<String, AutomaticZenRule>> getZenModeRules() { Map<String, AutomaticZenRule> ruleMap = NotificationManager.from(mContext).getAutomaticZenRules(); return ruleMap.entrySet(); } ...}知道上面的东西,ZenModeAutomationSettings就简单多了,就是mRules列表的展示,以及添加删除等操作。只是这里面添加可以选择两种模式,分别是活动规则和时间规则。分别对应的类是ZenModeEventRuleSettings和ZenModeScheduleRuleSettings,他们都继承自ZenModeRuleSettingsBase。这里ZenModeAutomationSettings虽然代码很多,但都是各种弹出框的操作,就不分析了。主要看看活动规则和时间规则这两个里面分别又有哪些操作吧。
时间规则的列表,分别有规则名称、星期几、开始时间、结束时间、勿扰、闹钟响铃时间可覆盖结束时间(在所设结束时间或下一次闹钟响铃时(两者选其先)停止)。由private ScheduleInfo mSchedule;中来存储着时间规则的一些数据。
活动规则的页面的列表,分别是名字、在以下日历活动期间、回复内容如下的活动、勿扰。由private EventInfo mEvent;中来存储着时间规则的一些数据。以上两个规则里面其余都只是进行一些修改操作。这些操作最后的修改的数据都会通过调用ZenModeRuleSettingsBase里面的updateRule()方法保存到NotificationManager里。代码如下:
Settings/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
mStart = new TimePickerPreference(getPrefContext(), mgr); mStart.setKey(KEY_START_TIME); mStart.setTitle(R.string.zen_mode_start_time); mStart.setCallback(new TimePickerPreference.Callback() { @Override public boolean onSetTime(final int hour, final int minute) { if (mDisableListeners) return true; if (!ZenModeConfig.isValidHour(hour)) return false; if (!ZenModeConfig.isValidMinute(minute)) return false; if (hour == mSchedule.startHour && minute == mSchedule.startMinute) { return true; } if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute); mSchedule.startHour = hour; mSchedule.startMinute = minute; updateRule(ZenModeConfig.toScheduleConditionId(mSchedule)); return true; } });Settings/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
protected void updateRule(Uri newConditionId) { mRule.setConditionId(newConditionId); setZenRule(mId, mRule); } protected boolean setZenRule(String id, AutomaticZenRule rule) { final boolean success = NotificationManager.from(mContext).updateAutomaticZenRule(id, rule); maybeRefreshRules(success, true); return success; }自此所有在Setting里面的勿扰模式的代码分析结束了,综上可知,Settings模块中勿扰只是一个界面的展示,其数据都放在NotificationManager进行管理操作。
新闻热点
疑难解答