首页 > 系统 > Android > 正文

Android7.1勿扰功能简析

2019-11-09 17:17:47
字体:
来源:转载
供稿:网友
Android系统在5.1系统开始增加勿扰模式,渐渐的有着取代静音模式的趋势,最新的系统已经更新到7.1.1,我们来看一下最新的原生勿扰有哪些功能。首先在屏幕下滑出来的快捷开关界面中,我们可以看到勿扰模式。在这里如果我们点击开启勿扰模式,会出现三种勿扰模式供选择。(1)完全静音:这会阻止所有声音和振动(包括闹钟、音乐、视频和游戏)打扰您。您仍然可以拨打电话。这里面也同事可以选择定时或者直到自己将其关闭。(2)仅限闹钟:这里面除了闹钟之外,别的都会阻止通知。(3)仅限优先打扰:您不会受声音和振动的打扰,但闹钟、提醒、活动和您指定的来电者除外。勿扰模式在设置中的位置,在声音设置下。进入勿扰的设置中,我们可以看到有如下三项设置:(1)仅允许优先打扰内容:设置在勿扰处于仅限优先打扰的时候,这种情况下,哪些联系人或者提醒等可以通知您。(2)自动规则:可以自定义多个自动规则,这些规则指哪些活动或者时间内自动开启勿扰模式。同时可以开启闹钟响铃时结束勿扰模式。(3)屏蔽视觉打扰:处于勿扰模式时的两种更优化方案的开关屏幕开启时屏蔽:禁止在勿扰模式下被静音的通知在屏幕上短暂显示或弹出屏幕关闭时屏蔽:禁止在勿扰模式下被静音的通知开启屏幕以上都是从手机上直接可以看出的原生系统的勿扰模式的功能。接下来从代码层面简单分析一下:首先勿扰模式的功能入口在SoundSettings.java中,布局文件局部如下:Settings/res/xml/sound_settings.xml
        <!-- 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进行管理操作。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表