Android7.1勿扰功能简析

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进行管理操作。



  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值