App & channel notification settings updates

- change 'block all' to an on/off switch bar
- update channel list summary text when notifications are
toggled on/off on app settings page
- Add 'off state' text
- change style of foot items
- change 'importance' from a dropdown to its own page

Bug: 37538972
Bug: 37479730
Fixes: 37541624
Fixes: 37549732
Test: manual

Change-Id: I0e5cc66ba539ce2b76b4ad6541bf6bfb5b58c373
This commit is contained in:
Julia Reynolds
2017-04-21 08:27:06 -04:00
parent 8da8951b4b
commit 38c16a9417
12 changed files with 489 additions and 140 deletions

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- For use in a LayoutPreference -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="0px"
android:layout_width="match_parent"
android:layout_weight="1" >
<com.android.settings.widget.SwitchBar
android:id="@+id/switch_bar"
android:layout_height="?android:attr/actionBarSize"
android:layout_width="match_parent"
android:paddingStart="0dp"
android:background="@drawable/switchbar_background"
android:theme="?attr/switchBarTheme"
/>
</LinearLayout>

View File

@@ -6558,7 +6558,10 @@
<!-- Notification Settings: Title for the option managing notifications per application. [CHAR LIMIT=30] --> <!-- Notification Settings: Title for the option managing notifications per application. [CHAR LIMIT=30] -->
<string name="app_notifications_title">Notifications</string> <string name="app_notifications_title">Notifications</string>
<!-- [CHAR LIMIT=100] Notification importance slider title --> <!-- [CHAR LIMIT=100] Notification channel title -->
<string name="notification_channel_title">Notification category</string>
<!-- [CHAR LIMIT=100] Notification importance screen title -->
<string name="notification_importance_title">Importance</string> <string name="notification_importance_title">Importance</string>
<!-- [CHAR LIMIT=100] Notification Importance: unspecified importance level description --> <!-- [CHAR LIMIT=100] Notification Importance: unspecified importance level description -->
@@ -6579,17 +6582,17 @@
<!-- [CHAR LIMIT=100] Notification Importance: high importance level description --> <!-- [CHAR LIMIT=100] Notification Importance: high importance level description -->
<string name="notification_importance_high">Make sound and pop on screen</string> <string name="notification_importance_high">Make sound and pop on screen</string>
<!-- [CHAR LIMIT=100] Notification Importance summary: min importance level description --> <!-- [CHAR LIMIT=100] Notification Importance title: min importance level title -->
<string name="notification_importance_min_summary">Low: No sound or visual interruption</string> <string name="notification_importance_min_title">Low</string>
<!-- [CHAR LIMIT=100] Notification Importance summary: low importance level description --> <!-- [CHAR LIMIT=100] Notification Importance title: low importance level title -->
<string name="notification_importance_low_summary">Medium: No sound</string> <string name="notification_importance_low_title">Medium</string>
<!-- [CHAR LIMIT=100] Notification Importance summary: normal importance level description --> <!-- [CHAR LIMIT=100] Notification Importance title: normal importance level title -->
<string name="notification_importance_default_summary">High: Make sound</string> <string name="notification_importance_default_title">High</string>
<!-- [CHAR LIMIT=100] Notification Importance summary: high importance level description --> <!-- [CHAR LIMIT=100] Notification Importance title: high importance level title -->
<string name="notification_importance_high_summary">Urgent: Make sound and pop on screen</string> <string name="notification_importance_high_title">Urgent</string>
<!-- [CHAR LIMIT=40] Notification importance title --> <!-- [CHAR LIMIT=40] Notification importance title -->
<string name="allow_sound">Allow Sound</string> <string name="allow_sound">Allow Sound</string>
@@ -6694,6 +6697,12 @@
<!-- [CHAR LIMIT=NONE] Text when loading app list in notification settings --> <!-- [CHAR LIMIT=NONE] Text when loading app list in notification settings -->
<string name="loading_notification_apps">Loading apps...</string> <string name="loading_notification_apps">Loading apps...</string>
<!-- [CHAR LIMIT=NONE] Text appearing when app notifications are off -->
<string name="app_notifications_off_desc">Android is blocking this app\'s notifications from appearing on this device</string>
<!-- [CHAR LIMIT=NONE] Text appearing when channel notifications are off -->
<string name="channel_notifications_off_desc">Android is blocking this category of notifications from appearing on this device</string>
<!-- [CHAR LIMIT=NONE] App notification settings: channels title --> <!-- [CHAR LIMIT=NONE] App notification settings: channels title -->
<string name="notification_channels">Categories</string> <string name="notification_channels">Categories</string>

View File

@@ -18,13 +18,6 @@
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/app_notifications_title" android:title="@string/app_notifications_title"
android:key="app_notification_settings"> android:key="app_notification_settings">
<!-- Block -->
<com.android.settingslib.RestrictedSwitchPreference
android:key="block"
android:title="@string/app_notification_block_title"
android:summary="@string/app_notification_block_summary"
settings:useAdditionalSummary="true"
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
<!-- Show badge --> <!-- Show badge -->
<com.android.settingslib.RestrictedSwitchPreference <com.android.settingslib.RestrictedSwitchPreference

View File

@@ -18,16 +18,7 @@
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" > xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" >
<!-- Importance --> <!-- Importance -->
<!-- Block --> <Preference
<com.android.settingslib.RestrictedSwitchPreference
android:key="block"
android:title="@string/app_notification_block_title"
android:summary="@string/app_notification_block_summary"
settings:useAdditionalSummary="true"
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
<!-- Importance -->
<com.android.settings.notification.RestrictedDropDownPreference
android:key="importance" android:key="importance"
android:title="@string/notification_importance_title" /> android:title="@string/notification_importance_title" />

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/notification_importance_title">
<com.android.settings.widget.RadioButtonPreference
android:key="importance_high"
android:title="@string/notification_importance_high_title"
android:summary="@string/notification_importance_high"
/>
<com.android.settings.widget.RadioButtonPreference
android:key="importance_default"
android:title="@string/notification_importance_default_title"
android:summary="@string/notification_importance_default" />
<com.android.settings.widget.RadioButtonPreference
android:key="importance_low"
android:title="@string/notification_importance_low_title"
android:summary="@string/notification_importance_low" />
<com.android.settings.widget.RadioButtonPreference
android:key="importance_min"
android:title="@string/notification_importance_min_title"
android:summary="@string/notification_importance_min" />
</PreferenceScreen>

View File

@@ -24,6 +24,7 @@ import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import android.app.Activity; import android.app.Activity;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationChannelGroup; import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
@@ -33,17 +34,22 @@ import android.support.v7.preference.PreferenceCategory;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.AppHeader; import com.android.settings.AppHeader;
import com.android.settings.DimmableIconPreference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.applications.AppHeaderController; import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.notification.NotificationBackend.AppRow; import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.FooterPreference;
import com.android.settings.widget.MasterSwitchPreference; import com.android.settings.widget.MasterSwitchPreference;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import java.text.Collator; import java.text.Collator;
@@ -57,12 +63,14 @@ public class AppNotificationSettings extends NotificationSettingsBase {
private static final String TAG = "AppNotificationSettings"; private static final String TAG = "AppNotificationSettings";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String KEY_BLOCK = "block";
private static final String KEY_IMPORTANCE = "allow_sound"; private static final String KEY_IMPORTANCE = "allow_sound";
private List<NotificationChannelGroup> mChannelGroupList; private List<NotificationChannelGroup> mChannelGroupList;
private List<PreferenceCategory> mChannelGroups = new ArrayList(); private List<PreferenceCategory> mChannelGroups = new ArrayList();
private RestrictedSwitchPreference mImportanceToggle; private RestrictedSwitchPreference mImportanceToggle;
private LayoutPreference mBlockBar;
private FooterPreference mDeletedChannels;
private SwitchBar mSwitchBar;
private boolean mShowLegacyChannelConfig = false; private boolean mShowLegacyChannelConfig = false;
@@ -88,8 +96,8 @@ public class AppNotificationSettings extends NotificationSettingsBase {
addPreferencesFromResource(R.xml.app_notification_settings); addPreferencesFromResource(R.xml.app_notification_settings);
getPreferenceScreen().setOrderingAsAdded(true); getPreferenceScreen().setOrderingAsAdded(true);
mBlock = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BLOCK);
mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE); mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
mBlockedDesc = (FooterPreference) getPreferenceScreen().findPreference(KEY_BLOCKED_DESC);
setupBlock(); setupBlock();
setupBadge(); setupBadge();
@@ -127,11 +135,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
.done(activity, getPrefContext()); .done(activity, getPrefContext());
getPreferenceScreen().addPreference(pref); getPreferenceScreen().addPreference(pref);
if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) { updateDependents(mAppRow.banned);
Log.w(TAG, "Missing package or uid or packageinfo");
finish();
return;
}
} }
private void populateChannelList() { private void populateChannelList() {
@@ -187,12 +191,12 @@ public class AppNotificationSettings extends NotificationSettingsBase {
int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid); int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid);
if (deletedChannelCount > 0) { if (deletedChannelCount > 0) {
DimmableIconPreference deletedPref = new DimmableIconPreference(getPrefContext()); mDeletedChannels = new FooterPreference(getPrefContext());
deletedPref.setSelectable(false); mDeletedChannels.setSelectable(false);
deletedPref.setTitle(getResources().getQuantityString( mDeletedChannels.setTitle(getResources().getQuantityString(
R.plurals.deleted_channels, deletedChannelCount, deletedChannelCount)); R.plurals.deleted_channels, deletedChannelCount, deletedChannelCount));
deletedPref.setIcon(R.drawable.ic_info); mDeletedChannels.setEnabled(false);
getPreferenceScreen().addPreference(deletedPref); getPreferenceScreen().addPreference(mDeletedChannels);
} }
} }
updateDependents(mAppRow.banned); updateDependents(mAppRow.banned);
@@ -214,7 +218,8 @@ public class AppNotificationSettings extends NotificationSettingsBase {
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId()); channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(), Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(),
ChannelNotificationSettings.class.getName(), ChannelNotificationSettings.class.getName(),
channelArgs, null, 0, null, false, getMetricsCategory()); channelArgs, null, R.string.notification_channel_title, null, false,
getMetricsCategory());
channelPref.setIntent(channelIntent); channelPref.setIntent(channelIntent);
channelPref.setOnPreferenceChangeListener( channelPref.setOnPreferenceChangeListener(
@@ -227,6 +232,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
channel.setImportance(importance); channel.setImportance(importance);
channel.lockFields( channel.lockFields(
NotificationChannel.USER_LOCKED_IMPORTANCE); NotificationChannel.USER_LOCKED_IMPORTANCE);
channelPref.setSummary(getImportanceSummary(channel.getImportance()));
mBackend.updateChannel(mPkg, mUid, channel); mBackend.updateChannel(mPkg, mUid, channel);
return true; return true;
@@ -237,8 +243,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
private void populateDefaultChannelPrefs() { private void populateDefaultChannelPrefs() {
addPreferencesFromResource(R.xml.legacy_channel_notification_settings); addPreferencesFromResource(R.xml.legacy_channel_notification_settings);
mPriority = mPriority = (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
(RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
mVisibilityOverride = mVisibilityOverride =
(RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE); (RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE);
mImportanceToggle = (RestrictedSwitchPreference) findPreference(KEY_IMPORTANCE); mImportanceToggle = (RestrictedSwitchPreference) findPreference(KEY_IMPORTANCE);
@@ -248,8 +253,11 @@ public class AppNotificationSettings extends NotificationSettingsBase {
setupVisOverridePref(mChannel.getLockscreenVisibility()); setupVisOverridePref(mChannel.getLockscreenVisibility());
setupImportanceToggle(); setupImportanceToggle();
} }
mSwitchBar.setChecked(!mAppRow.banned
&& mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
} }
// 'allow sound'
private void setupImportanceToggle() { private void setupImportanceToggle() {
mImportanceToggle.setDisabledByAdmin(mSuspendedAppsAdmin); mImportanceToggle.setDisabledByAdmin(mSuspendedAppsAdmin);
mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT
@@ -268,6 +276,40 @@ public class AppNotificationSettings extends NotificationSettingsBase {
}); });
} }
protected void setupBlock() {
View switchBarContainer = LayoutInflater.from(
getPrefContext()).inflate(R.layout.styled_switch_bar, null);
mSwitchBar = switchBarContainer.findViewById(R.id.switch_bar);
mSwitchBar.show();
mSwitchBar.setDisabledByAdmin(mSuspendedAppsAdmin);
mSwitchBar.setChecked(!mAppRow.banned);
mSwitchBar.addOnSwitchChangeListener(new SwitchBar.OnSwitchChangeListener() {
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (mShowLegacyChannelConfig && mChannel != null) {
final int importance = isChecked ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_NONE;
mImportanceToggle.setChecked(importance == IMPORTANCE_UNSPECIFIED);
mChannel.setImportance(importance);
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
mBackend.updateChannel(mPkg, mUid, mChannel);
}
mBackend.setNotificationsEnabledForPackage(mPkgInfo.packageName, mUid, isChecked);
updateDependents(!isChecked);
}
});
mBlockBar = new LayoutPreference(getPrefContext(), switchBarContainer);
mBlockBar.setOrder(-500);
mBlockBar.setKey(KEY_BLOCK);
getPreferenceScreen().addPreference(mBlockBar);
if (mAppRow.systemApp && !mAppRow.banned) {
setVisible(mBlockBar, false);
}
setupBlockDesc(R.string.app_notifications_off_desc);
}
private void setupBadge() { private void setupBadge() {
mBadge.setDisabledByAdmin(mSuspendedAppsAdmin); mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
mBadge.setChecked(mAppRow.showBadge); mBadge.setChecked(mAppRow.showBadge);
@@ -281,31 +323,14 @@ public class AppNotificationSettings extends NotificationSettingsBase {
}); });
} }
private void setupBlock() {
if (mAppRow.systemApp && !mAppRow.banned) {
setVisible(mBlock, false);
} else {
mBlock.setDisabledByAdmin(mSuspendedAppsAdmin);
mBlock.setChecked(mAppRow.banned);
mBlock.setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference,
Object newValue) {
final boolean blocked = (Boolean) newValue;
mBackend.setNotificationsEnabledForPackage(mPkgInfo.packageName, mUid,
!blocked);
updateDependents(blocked);
return true;
}
});
}
}
private void updateDependents(boolean banned) { private void updateDependents(boolean banned) {
for (PreferenceCategory category : mChannelGroups) { for (PreferenceCategory category : mChannelGroups) {
setVisible(category, !banned); setVisible(category, !banned);
} }
if (mDeletedChannels != null) {
setVisible(mDeletedChannels, !banned);
}
setVisible(mBlockedDesc, banned);
setVisible(mBadge, !banned); setVisible(mBadge, !banned);
if (mShowLegacyChannelConfig) { if (mShowLegacyChannelConfig) {
setVisible(mImportanceToggle, !banned); setVisible(mImportanceToggle, !banned);
@@ -313,7 +338,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
setVisible(mVisibilityOverride, !banned); setVisible(mVisibilityOverride, !banned);
} }
if (mAppRow.systemApp && !mAppRow.banned) { if (mAppRow.systemApp && !mAppRow.banned) {
setVisible(mBlock, false); setVisible(mBlockBar, false);
} }
} }

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import android.content.Context;
import android.provider.SearchIndexableResource;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.widget.RadioButtonPreference;
import java.util.ArrayList;
import java.util.List;
public class ChannelImportanceSettings extends NotificationSettingsBase
implements RadioButtonPreference.OnClickListener, Indexable {
private static final String TAG = "NotiImportance";
private static final String KEY_IMPORTANCE_HIGH = "importance_high";
private static final String KEY_IMPORTANCE_DEFAULT = "importance_default";
private static final String KEY_IMPORTANCE_LOW = "importance_low";
private static final String KEY_IMPORTANCE_MIN = "importance_min";
List<RadioButtonPreference> mImportances = new ArrayList<>();
@Override
public int getMetricsCategory() {
return MetricsEvent.NOTIFICATION_CHANNEL_IMPORTANCE;
}
@Override
public void onResume() {
super.onResume();
if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null || mChannel == null) {
Log.w(TAG, "Missing package or uid or packageinfo or channel");
finish();
return;
}
createPreferenceHierarchy();
}
@Override
public void onPause() {
super.onPause();
}
private PreferenceScreen createPreferenceHierarchy() {
PreferenceScreen root = getPreferenceScreen();
if (root != null) {
root.removeAll();
}
addPreferencesFromResource(R.xml.notification_importance);
root = getPreferenceScreen();
for (int i = 0; i < root.getPreferenceCount(); i++) {
Preference pref = root.getPreference(i);
if (pref instanceof RadioButtonPreference) {
RadioButtonPreference radioPref = (RadioButtonPreference) pref;
radioPref.setOnClickListener(this);
mImportances.add(radioPref);
}
}
switch (mChannel.getImportance()) {
case IMPORTANCE_MIN:
updateRadioButtons(KEY_IMPORTANCE_MIN);
break;
case IMPORTANCE_LOW:
updateRadioButtons(KEY_IMPORTANCE_LOW);
break;
case IMPORTANCE_DEFAULT:
updateRadioButtons(KEY_IMPORTANCE_DEFAULT);
break;
case IMPORTANCE_HIGH:
case IMPORTANCE_MAX:
updateRadioButtons(KEY_IMPORTANCE_HIGH);
break;
}
return root;
}
private void updateRadioButtons(String selectionKey) {
for (RadioButtonPreference pref : mImportances) {
if (selectionKey.equals(pref.getKey())) {
pref.setChecked(true);
} else {
pref.setChecked(false);
}
}
}
@Override
public void onRadioButtonClicked(RadioButtonPreference clicked) {
switch (clicked.getKey()) {
case KEY_IMPORTANCE_HIGH:
mChannel.setImportance(IMPORTANCE_HIGH);
break;
case KEY_IMPORTANCE_DEFAULT:
mChannel.setImportance(IMPORTANCE_DEFAULT);
break;
case KEY_IMPORTANCE_LOW:
mChannel.setImportance(IMPORTANCE_LOW);
break;
case KEY_IMPORTANCE_MIN:
mChannel.setImportance(IMPORTANCE_MIN);
break;
}
updateRadioButtons(clicked.getKey());
mChannel.lockFields(USER_LOCKED_IMPORTANCE);
mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, mChannel);
}
// This page exists per notification channel; should not be included
// in search
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
return null;
}
};
}

View File

@@ -16,9 +16,7 @@
package com.android.settings.notification; package com.android.settings.notification;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_NONE;
import android.app.Activity; import android.app.Activity;
@@ -27,25 +25,31 @@ import android.app.NotificationManager;
import android.content.Intent; import android.content.Intent;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import com.android.settings.DimmableIconPreference; import com.android.settings.AppHeader;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.RingtonePreference; import com.android.settings.RingtonePreference;
import com.android.settings.Utils;
import com.android.settings.applications.AppHeaderController; import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.FooterPreference;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import java.util.ArrayList;
import java.util.List;
public class ChannelNotificationSettings extends NotificationSettingsBase { public class ChannelNotificationSettings extends NotificationSettingsBase {
private static final String TAG = "ChannelSettings"; private static final String TAG = "ChannelSettings";
@@ -53,10 +57,13 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
protected static final String KEY_VIBRATE = "vibrate"; protected static final String KEY_VIBRATE = "vibrate";
protected static final String KEY_RINGTONE = "ringtone"; protected static final String KEY_RINGTONE = "ringtone";
protected Preference mImportance;
protected RestrictedSwitchPreference mLights; protected RestrictedSwitchPreference mLights;
protected RestrictedSwitchPreference mVibrate; protected RestrictedSwitchPreference mVibrate;
protected NotificationSoundPreference mRingtone; protected NotificationSoundPreference mRingtone;
protected LayoutPreference mBlockBar;
@Override @Override
public int getMetricsCategory() { public int getMetricsCategory() {
return MetricsEvent.NOTIFICATION_TOPIC_NOTIFICATION; return MetricsEvent.NOTIFICATION_TOPIC_NOTIFICATION;
@@ -75,33 +82,33 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
getPreferenceScreen().removeAll(); getPreferenceScreen().removeAll();
} }
addPreferencesFromResource(R.xml.channel_notification_settings); addPreferencesFromResource(R.xml.channel_notification_settings);
getPreferenceScreen().setOrderingAsAdded(true);
// load settings intent // load settings intent
ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<String, NotificationBackend.AppRow>(); ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<String, NotificationBackend.AppRow>();
rows.put(mAppRow.pkg, mAppRow); rows.put(mAppRow.pkg, mAppRow);
collectConfigActivities(rows); collectConfigActivities(rows);
mBlock = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BLOCK); mBlockedDesc = (FooterPreference) getPreferenceScreen().findPreference(KEY_BLOCKED_DESC);
mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE); mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
mImportance = (RestrictedDropDownPreference) findPreference(KEY_IMPORTANCE); mImportance = findPreference(KEY_IMPORTANCE);
mPriority = mPriority = (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
(RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
mVisibilityOverride = mVisibilityOverride =
(RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE); (RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE);
mLights = (RestrictedSwitchPreference) findPreference(KEY_LIGHTS); mLights = (RestrictedSwitchPreference) findPreference(KEY_LIGHTS);
mVibrate = (RestrictedSwitchPreference) findPreference(KEY_VIBRATE); mVibrate = (RestrictedSwitchPreference) findPreference(KEY_VIBRATE);
mRingtone = (NotificationSoundPreference) findPreference(KEY_RINGTONE); mRingtone = (NotificationSoundPreference) findPreference(KEY_RINGTONE);
if (mPkgInfo != null && mChannel != null) {
setupPriorityPref(mChannel.canBypassDnd()); setupPriorityPref(mChannel.canBypassDnd());
setupVisOverridePref(mChannel.getLockscreenVisibility()); setupVisOverridePref(mChannel.getLockscreenVisibility());
setupLights(); setupLights();
setupVibrate(); setupVibrate();
setupRingtone(); setupRingtone();
setupBlockAndImportance(); setupBadge();
setupBlock();
setupImportance();
updateDependents(); updateDependents();
}
final Activity activity = getActivity(); final Activity activity = getActivity();
final Preference pref = FeatureFactory.getFactory(activity) final Preference pref = FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity) .getApplicationFeatureProvider(activity)
@@ -124,12 +131,13 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
} }
if (!TextUtils.isEmpty(mChannel.getDescription())) { if (!TextUtils.isEmpty(mChannel.getDescription())) {
DimmableIconPreference descPref = new DimmableIconPreference(getPrefContext()); FooterPreference descPref = new FooterPreference(getPrefContext());
descPref.setSelectable(false); descPref.setSelectable(false);
descPref.setSummary(mChannel.getDescription()); descPref.setSummary(mChannel.getDescription());
descPref.setIcon(R.drawable.ic_info); descPref.setEnabled(false);
getPreferenceScreen().addPreference(descPref); getPreferenceScreen().addPreference(descPref);
} }
} }
private void setupLights() { private void setupLights() {
@@ -175,27 +183,38 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
}); });
} }
protected void setupBlockAndImportance() { protected void setupBlock() {
if (mAppRow.systemApp && mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE) { View switchBarContainer = LayoutInflater.from(
setVisible(mBlock, false); getPrefContext()).inflate(R.layout.styled_switch_bar, null);
} else { SwitchBar switchBar = switchBarContainer.findViewById(R.id.switch_bar);
mBlock.setEnabled(mAppRow.systemApp); switchBar.show();
mBlock.setDisabledByAdmin(mSuspendedAppsAdmin); switchBar.setDisabledByAdmin(mSuspendedAppsAdmin);
mBlock.setChecked(mChannel.getImportance() == NotificationManager.IMPORTANCE_NONE); switchBar.setChecked(mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
mBlock.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { switchBar.addOnSwitchChangeListener(new SwitchBar.OnSwitchChangeListener() {
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public void onSwitchChanged(Switch switchView, boolean isChecked) {
final boolean value = (Boolean) newValue; int importance = isChecked ? IMPORTANCE_LOW : IMPORTANCE_NONE;
int importance = value ? IMPORTANCE_NONE : IMPORTANCE_LOW; mImportance.setSummary(getImportanceSummary(importance));
mImportance.setValue(String.valueOf(importance));
mChannel.setImportance(importance); mChannel.setImportance(importance);
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE); mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
mBackend.updateChannel(mPkg, mUid, mChannel); mBackend.updateChannel(mPkg, mUid, mChannel);
updateDependents(); updateDependents();
return true;
} }
}); });
mBlockBar = new LayoutPreference(getPrefContext(), switchBarContainer);
mBlockBar.setOrder(-500);
mBlockBar.setKey(KEY_BLOCK);
getPreferenceScreen().addPreference(mBlockBar);
if (mAppRow.systemApp && mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE) {
setVisible(mBlockBar, false);
} }
setupBlockDesc(R.string.channel_notifications_off_desc);
}
protected void setupBadge() {
mBadge.setDisabledByAdmin(mSuspendedAppsAdmin); mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
mBadge.setEnabled(mAppRow.showBadge); mBadge.setEnabled(mAppRow.showBadge);
mBadge.setChecked(mChannel.canShowBadge()); mBadge.setChecked(mChannel.canShowBadge());
@@ -209,41 +228,21 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
return true; return true;
} }
}); });
mImportance.setDisabledByAdmin(mSuspendedAppsAdmin);
final int numImportances = IMPORTANCE_HIGH - IMPORTANCE_MIN + 1;
List<String> summaries = new ArrayList<>();
List<String> values = new ArrayList<>();
for (int i = 0; i < numImportances; i++) {
int importance = i + 1;
summaries.add(getImportanceSummary(importance));
values.add(String.valueOf(importance));
} }
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
// Add option to reset to letting the app decide protected void setupImportance() {
summaries.add(getImportanceSummary(NotificationManager.IMPORTANCE_UNSPECIFIED)); Bundle channelArgs = new Bundle();
values.add(String.valueOf(NotificationManager.IMPORTANCE_UNSPECIFIED)); channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
} channelArgs.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
mImportance.setEntryValues(values.toArray(new String[0])); channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
mImportance.setEntries(summaries.toArray(new String[0])); channelArgs.putString(Settings.EXTRA_CHANNEL_ID, mChannel.getId());
mImportance.setValue(String.valueOf(mChannel.getImportance())); Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(),
ChannelImportanceSettings.class.getName(),
channelArgs, null, R.string.notification_importance_title, null,
false, getMetricsCategory());
mImportance.setIntent(channelIntent);
mImportance.setEnabled(mSuspendedAppsAdmin == null);
mImportance.setSummary(getImportanceSummary(mChannel.getImportance())); mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
if (mAppRow.lockedImportance) {
mImportance.setEnabled(false);
} else {
mImportance.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int importance = Integer.parseInt((String) newValue);
mChannel.setImportance(importance);
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
mBackend.updateChannel(mPkg, mUid, mChannel);
updateDependents();
return true;
}
});
}
} }
private boolean isLockScreenSecure() { private boolean isLockScreenSecure() {
@@ -292,6 +291,7 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
} }
private void updateDependents() { private void updateDependents() {
setVisible(mBlockedDesc, mChannel.getImportance() == IMPORTANCE_NONE);
setVisible(mBadge, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN)); setVisible(mBadge, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
setVisible(mImportance, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN)); setVisible(mImportance, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
setVisible(mLights, checkCanBeVisible( setVisible(mLights, checkCanBeVisible(

View File

@@ -19,6 +19,7 @@ package com.android.settings.notification;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppInfoBase;
import com.android.settings.widget.FooterPreference;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
@@ -39,6 +40,7 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArrayMap; import android.util.ArrayMap;
@@ -63,6 +65,7 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
protected static final String KEY_BYPASS_DND = "bypass_dnd"; protected static final String KEY_BYPASS_DND = "bypass_dnd";
protected static final String KEY_VISIBILITY_OVERRIDE = "visibility_override"; protected static final String KEY_VISIBILITY_OVERRIDE = "visibility_override";
protected static final String KEY_IMPORTANCE = "importance"; protected static final String KEY_IMPORTANCE = "importance";
protected static final String KEY_BLOCKED_DESC = "block_desc";
protected PackageManager mPm; protected PackageManager mPm;
protected UserManager mUm; protected UserManager mUm;
@@ -73,11 +76,10 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
protected int mUserId; protected int mUserId;
protected String mPkg; protected String mPkg;
protected PackageInfo mPkgInfo; protected PackageInfo mPkgInfo;
protected RestrictedSwitchPreference mBlock;
protected RestrictedSwitchPreference mBadge; protected RestrictedSwitchPreference mBadge;
protected RestrictedDropDownPreference mImportance;
protected RestrictedSwitchPreference mPriority; protected RestrictedSwitchPreference mPriority;
protected RestrictedDropDownPreference mVisibilityOverride; protected RestrictedDropDownPreference mVisibilityOverride;
protected FooterPreference mBlockedDesc;
protected EnforcedAdmin mSuspendedAppsAdmin; protected EnforcedAdmin mSuspendedAppsAdmin;
protected boolean mDndVisualEffectsSuppressed; protected boolean mDndVisualEffectsSuppressed;
@@ -325,6 +327,15 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
mVisibilityOverride.setDisabledByAdmin(mSuspendedAppsAdmin); mVisibilityOverride.setDisabledByAdmin(mSuspendedAppsAdmin);
} }
protected void setupBlockDesc(int summaryResId) {
mBlockedDesc = new FooterPreference(getPrefContext());
mBlockedDesc.setSelectable(false);
mBlockedDesc.setTitle(summaryResId);
mBlockedDesc.setEnabled(false);
mBlockedDesc.setOrder(50);
getPreferenceScreen().addPreference(mBlockedDesc);
}
private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry, private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
CharSequence entryValue, int keyguardNotificationFeatures) { CharSequence entryValue, int keyguardNotificationFeatures) {

View File

@@ -1,3 +1,19 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification; package com.android.settings.notification;
import android.content.ContentResolver; import android.content.ContentResolver;

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.content.Context;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.widget.ToggleSwitch;
import com.android.settingslib.RestrictedLockUtils;
public class NotificationSwitchBarPreference extends LayoutPreference {
private ToggleSwitch mSwitch;
private boolean mChecked;
private boolean mEnableSwitch = true;
public NotificationSwitchBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mSwitch = (ToggleSwitch) holder.findViewById(android.R.id.switch_widget);
if (mSwitch != null) {
mSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mSwitch.isEnabled()) {
return;
}
mChecked = !mChecked;
setChecked(mChecked);
if (!callChangeListener(mChecked)) {
setChecked(!mChecked);
}
}
});
mSwitch.setChecked(mChecked);
mSwitch.setEnabled(mEnableSwitch);
}
}
public boolean isChecked() {
return mSwitch != null && mSwitch.isEnabled() && mChecked;
}
public void setChecked(boolean checked) {
mChecked = checked;
if (mSwitch != null) {
mSwitch.setChecked(checked);
}
}
public void setSwitchEnabled(boolean enabled) {
mEnableSwitch = enabled;
if (mSwitch != null) {
mSwitch.setEnabled(enabled);
}
}
public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
setSwitchEnabled(admin == null);
}
}

View File

@@ -65,6 +65,7 @@ import com.android.settings.location.LocationSettings;
import com.android.settings.location.ScanningSettings; import com.android.settings.location.ScanningSettings;
import com.android.settings.network.NetworkDashboardFragment; import com.android.settings.network.NetworkDashboardFragment;
import com.android.settings.nfc.PaymentSettings; import com.android.settings.nfc.PaymentSettings;
import com.android.settings.notification.ChannelImportanceSettings;
import com.android.settings.notification.ConfigureNotificationSettings; import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.SoundSettings; import com.android.settings.notification.SoundSettings;
import com.android.settings.notification.ZenModePrioritySettings; import com.android.settings.notification.ZenModePrioritySettings;
@@ -179,6 +180,8 @@ public final class SearchIndexableResources {
R.drawable.ic_settings_accessibility); R.drawable.ic_settings_accessibility);
addIndex(AccessibilityShortcutPreferenceFragment.class, NO_DATA_RES_ID, addIndex(AccessibilityShortcutPreferenceFragment.class, NO_DATA_RES_ID,
R.drawable.ic_settings_accessibility); R.drawable.ic_settings_accessibility);
addIndex(ChannelImportanceSettings.class, NO_DATA_RES_ID,
R.drawable.ic_settings_notifications);
} }
private SearchIndexableResources() { private SearchIndexableResources() {