Android7.1勿扰功能简析

来源:互联网 发布:淘宝网婚房纱幔 编辑:程序博客网 时间:2024/06/05 05:44
 

Android7.1勿扰功能简析

标签: android源码
 1257人阅读 评论(0) 收藏 举报
 分类:
Android系统在5.1系统开始增加勿扰模式,渐渐的有着取代静音模式的趋势,最新的系统已经更新到7.1.1,我们来看一下最新的原生勿扰有哪些功能。
首先在屏幕下滑出来的快捷开关界面中,我们可以看到勿扰模式。在这里如果我们点击开启勿扰模式,会出现三种勿扰模式供选择。
(1)完全静音:这会阻止所有声音和振动(包括闹钟、音乐、视频和游戏)打扰您。您仍然可以拨打电话。这里面也同事可以选择定时或者直到自己将其关闭。
(2)仅限闹钟:这里面除了闹钟之外,别的都会阻止通知。
(3)仅限优先打扰:您不会受声音和振动的打扰,但闹钟、提醒、活动和您指定的来电者除外。
勿扰模式在设置中的位置,在声音设置下。进入勿扰的设置中,我们可以看到有如下三项设置:
(1)仅允许优先打扰内容:设置在勿扰处于仅限优先打扰的时候,这种情况下,哪些联系人或者提醒等可以通知您。
(2)自动规则:可以自定义多个自动规则,这些规则指哪些活动或者时间内自动开启勿扰模式。同时可以开启闹钟响铃时结束勿扰模式。
(3)屏蔽视觉打扰:处于勿扰模式时的两种更优化方案的开关
  • 屏幕开启时屏蔽:禁止在勿扰模式下被静音的通知在屏幕上短暂显示或弹出
  • 屏幕关闭时屏蔽:禁止在勿扰模式下被静音的通知开启屏幕
以上都是从手机上直接可以看出的原生系统的勿扰模式的功能。接下来从代码层面简单分析一下:首先勿扰模式的功能入口在SoundSettings.java中,布局文件局部如下:Settings\res\xml\sound_settings.xml
[html] view plain copy
  1. <!-- Interruptions -->  
  2. <com.android.settingslib.RestrictedPreference  
  3.         android:key="zen_mode"  
  4.         android:title="@string/zen_mode_settings_title"  
  5.         settings:useAdminDisabledSummary="true"  
  6.         settings:keywords="@string/keywords_sounds_and_notifications_interruptions"  
  7.         android:fragment="com.android.settings.notification.ZenModeSettings" />  
点击勿扰选项进入ZenModeSettings中。ZenModeSettings中的布局文件为zen_mode_settings,如下:
Settings\res\xml\zen_mode_settings.xml
[html] view plain copy
  1. <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:key="zen_mode_settings"  
  3.     android:title="@string/zen_mode_settings_title" >  
  4.   
  5.     <!-- Priority only allows -->  
  6.     <PreferenceScreen  
  7.             android:key="priority_settings"  
  8.             android:title="@string/zen_mode_priority_settings_title"  
  9.             android:fragment="com.android.settings.notification.ZenModePrioritySettings" />  
  10.   
  11.     <!-- Automated rules -->  
  12.     <PreferenceScreen  
  13.             android:key="automation_settings"  
  14.             android:title="@string/zen_mode_automation_settings_title"  
  15.             android:fragment="com.android.settings.notification.ZenModeAutomationSettings" />  
  16.   
  17.     <!-- Visual interruptions -->  
  18.     <PreferenceScreen  
  19.             android:key="visual_interruptions_settings"  
  20.             android:title="@string/zen_mode_visual_interruptions_settings_title"  
  21.             android:fragment="com.android.settings.notification.ZenModeVisualInterruptionSettings" />  
  22. </PreferenceScreen>  

上面的布局文件和我们从手机上看到的勿扰设置界面一样。我们可以看出ZenModePrioritySettings 、ZenModeAutomationSettings 、ZenModeVisualInterruptionSettings分别对应着仅允许优先打扰内容、自动规则、屏蔽视觉打扰三种页面。

ZenModeSettings、ZenModePrioritySettings、ZenModeAutomationSettings 、ZenModeVisualInterruptionSettings都继承于ZenModeSettingsBase。我们来分别看一下这些类。

ZenModeSettings这个类,我们从代码中可以看出它只是三项设置界面的入口,以及对勿扰的更新做一些界面的显示工作。如下代码:

Settings/src/com/android/settings/notification/ZenModeSettings.java

[java] view plain copy
  1. @Override  
  2. protected void onZenModeChanged() {  
  3.     updateControls();  
  4. }  
  5.   
  6. @Override  
  7. protected void onZenModeConfigChanged() {  
  8.     mPolicy = NotificationManager.from(mContext).getNotificationPolicy();  
  9.     updateControls();  
  10. }  
  11.   
  12. private void updateControls() {  
  13.     updatePrioritySettingsSummary();  
  14.     updateVisualSettingsSummary();  
  15. }  
  16.   
  17. private void updatePrioritySettingsSummary() {  
  18.     String s = getResources().getString(R.string.zen_mode_alarms);  
  19.     s = appendLowercase(s, isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_REMINDERS),  
  20.             R.string.zen_mode_reminders);  
  21.     s = appendLowercase(s, isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_EVENTS),  
  22.             R.string.zen_mode_events);  
  23.     if (isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_MESSAGES)) {  
  24.         if (mPolicy.priorityMessageSenders == Policy.PRIORITY_SENDERS_ANY) {  
  25.             s = appendLowercase(s, true, R.string.zen_mode_all_messages);  
  26.         } else {  
  27.             s = appendLowercase(s, true, R.string.zen_mode_selected_messages);  
  28.         }  
  29.     }  
  30.     if (isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_CALLS)) {  
  31.         if (mPolicy.priorityCallSenders == Policy.PRIORITY_SENDERS_ANY) {  
  32.             s = appendLowercase(s, true, R.string.zen_mode_all_callers);  
  33.         } else {  
  34.             s = appendLowercase(s, true, R.string.zen_mode_selected_callers);  
  35.         }  
  36.     } else if (isCategoryEnabled(mPolicy, Policy.PRIORITY_CATEGORY_REPEAT_CALLERS)) {  
  37.         s = appendLowercase(s, true, R.string.zen_mode_repeat_callers);  
  38.     }  
  39.     mPrioritySettings.setSummary(s);  
  40. }  
  41.   
  42. private void updateVisualSettingsSummary() {  
  43.     String s = getString(R.string.zen_mode_all_visual_interruptions);  
  44.     if (isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_ON)  
  45.             && isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF)) {  
  46.         s = getString(R.string.zen_mode_no_visual_interruptions);  
  47.     } else if (isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_ON)) {  
  48.         s = getString(R.string.zen_mode_screen_on_visual_interruptions);  
  49.     } else if (isEffectSuppressed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF)) {  
  50.         s = getString(R.string.zen_mode_screen_off_visual_interruptions);  
  51.     }  
  52.     mVisualSettings.setSummary(s);  
  53. }  
我们再看ZenModePrioritySettings类,首先它负责自定义优先打扰的内容,其中包括闹钟、提醒、活动、消息、通话(仅限来自联系人)、重复来电者(如果同一个人在15分钟内第二次来电,则允许显示通知)。这面也仅是一些开关,将最后的更改用NotificationManager.from(mContext).setNotificationPolicy(mPolicy);进行保存,其中也只有消息和通话需要选择,我们来看一下通话的设置以及保存,其余的类似:

Settings/src/com/android/settings/notification/ZenModePrioritySettings.java

[java] view plain copy
  1. @Override  
  2. public void onCreate(Bundle savedInstanceState) {  
  3.     super.onCreate(savedInstanceState);  
  4.     addPreferencesFromResource(R.xml.zen_mode_priority_settings);  
  5.     final PreferenceScreen root = getPreferenceScreen();  
  6.   
  7.     mPolicy = NotificationManager.from(mContext).getNotificationPolicy();  
  8.   
  9.     ...  
  10.   
  11.     mCalls = (DropDownPreference) root.findPreference(KEY_CALLS);  
  12.     addSources(mCalls);  
  13.     mCalls.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {  
  14.         @Override  
  15.         public boolean onPreferenceChange(Preference preference, Object newValue) {  
  16.             if (mDisableListeners) return false;  
  17.             final int val = Integer.parseInt((String) newValue);  
  18.             final boolean allowCalls = val != SOURCE_NONE;  
  19.             final int allowCallsFrom = val == SOURCE_NONE ? mPolicy.priorityCallSenders : val;  
  20.             MetricsLogger.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_CALLS, val);  
  21.             if (DEBUG) Log.d(TAG, "onPrefChange allowCalls=" + allowCalls  
  22.                     + " allowCallsFrom=" + ZenModeConfig.sourceToString(allowCallsFrom));  
  23.             savePolicy(getNewPriorityCategories(allowCalls, Policy.PRIORITY_CATEGORY_CALLS),  
  24.                     allowCallsFrom, mPolicy.priorityMessageSenders,  
  25.                     mPolicy.suppressedVisualEffects);  
  26.             return true;  
  27.         }  
  28.     });  
  29.   
  30.     ...  
  31.   
  32.     updateControls();  
  33. }  
  34.   
  35. private void updateControls() {  
  36.     mDisableListeners = true;  
  37.     if (mCalls != null) {  
  38.         mCalls.setValue(Integer.toString(  
  39.                 isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS)  
  40.                         ? mPolicy.priorityCallSenders : SOURCE_NONE));  
  41.     }  
  42.     mMessages.setValue(Integer.toString(  
  43.             isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_MESSAGES)  
  44.                     ? mPolicy.priorityMessageSenders : SOURCE_NONE));  
  45.     mReminders.setChecked(isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REMINDERS));  
  46.     mEvents.setChecked(isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_EVENTS));  
  47.     mRepeatCallers.setChecked(  
  48.             isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS));  
  49.     mRepeatCallers.setVisible(!isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS)  
  50.             || mPolicy.priorityCallSenders != Policy.PRIORITY_SENDERS_ANY);  
  51.     mDisableListeners = false;  
  52. }  
  53.   
  54. private void savePolicy(int priorityCategories, int priorityCallSenders,  
  55.         int priorityMessageSenders, int suppressedVisualEffects) {  
  56.     mPolicy = new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders,  
  57.             suppressedVisualEffects);  
  58.     NotificationManager.from(mContext).setNotificationPolicy(mPolicy);  
  59. }  

ZenModeVisualInterruptionSettings和ZenModePrioritySettings类似,只是换成了屏幕开启时屏蔽和屏幕关闭时屏蔽两个开关,所以就不分析了。我们看ZenModeAutomationSettings这个稍微不同的类。

在ZenModeSettingsBase中有一个mRules的集合,存储着用户自己定义的AutomaticZenRule,而mRules的值是NotificationManager中获取的的。也就是这里规则的维护存储也还是在NotificationManager中,如下代码。

Settings/src/com/android/settings/notification/ZenModeSettingsBase.java

[java] view plain copy
  1. abstract public class ZenModeSettingsBase extends RestrictedSettingsFragment {  
  2.     ...  
  3.       
  4.     protected Context mContext;  
  5.     protected Set<Map.Entry<String, AutomaticZenRule>> mRules;  
  6.       
  7.     ...  
  8.   
  9.     private void updateZenMode(boolean fireChanged) {  
  10.         final int zenMode = Settings.Global.getInt(getContentResolver(), Global.ZEN_MODE, mZenMode);  
  11.         if (zenMode == mZenMode) return;  
  12.         mZenMode = zenMode;  
  13.         if (DEBUG) Log.d(TAG, "updateZenMode mZenMode=" + mZenMode);  
  14.         if (fireChanged) {  
  15.             onZenModeChanged();  
  16.         }  
  17.     }  
  18.   
  19.     protected String addZenRule(AutomaticZenRule rule) {  
  20.         try {  
  21.             String id = NotificationManager.from(mContext).addAutomaticZenRule(rule);  
  22.             final AutomaticZenRule savedRule =  
  23.                     NotificationManager.from(mContext).getAutomaticZenRule(id);  
  24.             maybeRefreshRules(savedRule != nulltrue);  
  25.             return id;  
  26.         } catch (Exception e) {  
  27.             return null;  
  28.         }  
  29.     }  
  30.   
  31.     protected boolean setZenRule(String id, AutomaticZenRule rule) {  
  32.         final boolean success =  
  33.                 NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);  
  34.         maybeRefreshRules(success, true);  
  35.         return success;  
  36.     }  
  37.   
  38.     protected boolean removeZenRule(String id) {  
  39.         final boolean success =  
  40.                 NotificationManager.from(mContext).removeAutomaticZenRule(id);  
  41.         maybeRefreshRules(success, true);  
  42.         return success;  
  43.     }  
  44.   
  45.     protected void maybeRefreshRules(boolean success, boolean fireChanged) {  
  46.         if (success) {  
  47.             mRules = getZenModeRules();  
  48.             if (DEBUG) Log.d(TAG, "Refreshed mRules=" + mRules);  
  49.             if (fireChanged) {  
  50.                 onZenModeConfigChanged();  
  51.             }  
  52.         }  
  53.     }  
  54.   
  55.     protected void setZenMode(int zenMode, Uri conditionId) {  
  56.         NotificationManager.from(mContext).setZenMode(zenMode, conditionId, TAG);  
  57.     }  
  58.   
  59.     private Set<Map.Entry<String, AutomaticZenRule>> getZenModeRules() {  
  60.         Map<String, AutomaticZenRule> ruleMap  
  61.                 = NotificationManager.from(mContext).getAutomaticZenRules();  
  62.         return ruleMap.entrySet();  
  63.     }  
  64.   
  65.     ...  
  66. }  

知道上面的东西,ZenModeAutomationSettings就简单多了,就是mRules列表的展示,以及添加删除等操作。只是这里面添加可以选择两种模式,分别是活动规则和时间规则。分别对应的类是ZenModeEventRuleSettings和ZenModeScheduleRuleSettings,他们都继承自ZenModeRuleSettingsBase。这里ZenModeAutomationSettings虽然代码很多,但都是各种弹出框的操作,就不分析了。主要看看活动规则和时间规则这两个里面分别又有哪些操作吧。

时间规则的列表,分别有规则名称、星期几、开始时间、结束时间、勿扰、闹钟响铃时间可覆盖结束时间(在所设结束时间或下一次闹钟响铃时(两者选其先)停止)。由private ScheduleInfo mSchedule;中来存储着时间规则的一些数据。

活动规则的页面的列表,分别是名字、在以下日历活动期间、回复内容如下的活动、勿扰。由private EventInfo mEvent;中来存储着时间规则的一些数据。以上两个规则里面其余都只是进行一些修改操作。这些操作最后的修改的数据都会通过调用ZenModeRuleSettingsBase里面的updateRule()方法保存到NotificationManager里。代码如下:

Settings/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java

[java] view plain copy
  1. mStart = new TimePickerPreference(getPrefContext(), mgr);  
  2. mStart.setKey(KEY_START_TIME);  
  3. mStart.setTitle(R.string.zen_mode_start_time);  
  4. mStart.setCallback(new TimePickerPreference.Callback() {  
  5.     @Override  
  6.     public boolean onSetTime(final int hour, final int minute) {  
  7.         if (mDisableListeners) return true;  
  8.         if (!ZenModeConfig.isValidHour(hour)) return false;  
  9.         if (!ZenModeConfig.isValidMinute(minute)) return false;  
  10.         if (hour == mSchedule.startHour && minute == mSchedule.startMinute) {  
  11.             return true;  
  12.         }  
  13.         if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute);  
  14.         mSchedule.startHour = hour;  
  15.         mSchedule.startMinute = minute;  
  16.         updateRule(ZenModeConfig.toScheduleConditionId(mSchedule));  
  17.         return true;  
  18.     }  
  19. });  

Settings/src/com/android/settings/notification/ZenModeRuleSettingsBase.java

[java] view plain copy
  1. protected void updateRule(Uri newConditionId) {  
  2.     mRule.setConditionId(newConditionId);  
  3.     setZenRule(mId, mRule);  
  4. }  
  5.   
  6. protected boolean setZenRule(String id, AutomaticZenRule rule) {  
  7.     final boolean success =  
  8.             NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);  
  9.     maybeRefreshRules(success, true);  
  10.     return success;  
  11. }  

自此所有在Setting里面的勿扰模式的代码分析结束了,综上可知,Settings模块中勿扰只是一个界面的展示,其数据都放在NotificationManager进行管理操作。


原创粉丝点击