Allow users to set notification topic importance.
In the absence of mocks, the silder is shown in the 'normal' position if the user hasn't yet chosen an importance value. Bug: 22854014 Change-Id: I51594959412775fe89b29af66ddcb13bafa67255
This commit is contained in:
81
res/layout/preference_importance_slider.xml
Normal file
81
res/layout/preference_importance_slider.xml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2015 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:paddingTop="8dip"
|
||||||
|
android:paddingBottom="8dip">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:fadingEdge="horizontal" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/summary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignStart="@android:id/title"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:maxLines="10"
|
||||||
|
android:minLines="2" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="6dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/low_importance"
|
||||||
|
android:src="@android:drawable/ic_menu_close_clear_cancel"
|
||||||
|
android:layout_gravity="center_vertical|start"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp" />
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:id="@*android:id/seekbar"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:focusable="true"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/max_importance"
|
||||||
|
android:src="@android:drawable/ic_popup_reminder"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@@ -20,7 +20,8 @@
|
|||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:clickable="false" >
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@@ -6124,6 +6124,9 @@
|
|||||||
<!-- [CHAR LIMIT=20] Notification settings: App notifications dialog dismiss button caption -->
|
<!-- [CHAR LIMIT=20] Notification settings: App notifications dialog dismiss button caption -->
|
||||||
<string name="app_notifications_dialog_done">Done</string>
|
<string name="app_notifications_dialog_done">Done</string>
|
||||||
|
|
||||||
|
<!-- [CHAR LIMIT=150] App notification settings: App notifications Importance title -->
|
||||||
|
<string name="app_notification_importance_title">Importance</string>
|
||||||
|
|
||||||
<!-- [CHAR LIMIT=40] Zen mode settings: Rule name option and edit dialog title -->
|
<!-- [CHAR LIMIT=40] Zen mode settings: Rule name option and edit dialog title -->
|
||||||
<string name="zen_mode_rule_name">Rule name</string>
|
<string name="zen_mode_rule_name">Rule name</string>
|
||||||
|
|
||||||
|
@@ -18,6 +18,13 @@
|
|||||||
android:title="@string/topic_notifications_title"
|
android:title="@string/topic_notifications_title"
|
||||||
android:key="topic_notification_settings">
|
android:key="topic_notification_settings">
|
||||||
|
|
||||||
|
<!-- Importance -->
|
||||||
|
<com.android.settings.notification.ImportanceSeekBarPreference
|
||||||
|
android:key="importance"
|
||||||
|
android:title="@string/app_notification_importance_title"
|
||||||
|
android:order="1"
|
||||||
|
android:persistent="false" />
|
||||||
|
|
||||||
<!-- Bypass DND -->
|
<!-- Bypass DND -->
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="bypass_dnd"
|
android:key="bypass_dnd"
|
||||||
|
@@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2015 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 com.android.settings.R;
|
||||||
|
import com.android.settings.SeekBarPreference;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.service.notification.NotificationListenerService;
|
||||||
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A slider preference that controls notification importance.
|
||||||
|
**/
|
||||||
|
public class ImportanceSeekBarPreference extends SeekBarPreference implements
|
||||||
|
SeekBar.OnSeekBarChangeListener {
|
||||||
|
private static final String TAG = "ImportanceSeekBarPref";
|
||||||
|
|
||||||
|
public static final int IMPORTANCE_PROGRESS_OFFSET = 2;
|
||||||
|
private Callback mCallback;
|
||||||
|
private TextView mSummaryTextView;
|
||||||
|
private String mSummary;
|
||||||
|
|
||||||
|
public ImportanceSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
|
||||||
|
int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
setLayoutResource(R.layout.preference_importance_slider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportanceSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
this(context, attrs, defStyleAttr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportanceSeekBarPreference(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportanceSeekBarPreference(Context context) {
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallback(Callback callback) {
|
||||||
|
mCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||||
|
super.onBindViewHolder(view);
|
||||||
|
mSummaryTextView = (TextView) view.findViewById(com.android.internal.R.id.summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProgress(int progress) {
|
||||||
|
mSummary = getProgressSummary(progress);
|
||||||
|
super.setProgress(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, final int progress, boolean fromTouch) {
|
||||||
|
super.onProgressChanged(seekBar, progress, fromTouch);
|
||||||
|
if (mSummaryTextView != null) {
|
||||||
|
mSummaryTextView.setText(getProgressSummary(progress));
|
||||||
|
}
|
||||||
|
if (fromTouch) {
|
||||||
|
mCallback.onImportanceChanged(progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence getSummary() {
|
||||||
|
return mSummary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getProgressSummary(int progress) {
|
||||||
|
// Map progress 0-4 values to Importance's -2-2.
|
||||||
|
progress = progress - IMPORTANCE_PROGRESS_OFFSET;
|
||||||
|
switch (progress) {
|
||||||
|
case NotificationListenerService.Ranking.IMPORTANCE_NONE:
|
||||||
|
return getContext().getString(
|
||||||
|
com.android.internal.R.string.notification_importance_blocked);
|
||||||
|
case NotificationListenerService.Ranking.IMPORTANCE_LOW:
|
||||||
|
return getContext().getString(
|
||||||
|
com.android.internal.R.string.notification_importance_low);
|
||||||
|
case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
|
||||||
|
return getContext().getString(
|
||||||
|
com.android.internal.R.string.notification_importance_default);
|
||||||
|
case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
|
||||||
|
return getContext().getString(
|
||||||
|
com.android.internal.R.string.notification_importance_high);
|
||||||
|
case NotificationListenerService.Ranking.IMPORTANCE_MAX:
|
||||||
|
return getContext().getString(
|
||||||
|
com.android.internal.R.string.notification_importance_max);
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Callback {
|
||||||
|
void onImportanceChanged(int progress);
|
||||||
|
}
|
||||||
|
}
|
@@ -62,6 +62,7 @@ public class NotificationBackend {
|
|||||||
row.priority = getBypassZenMode(row.pkg, row.uid, row.topic);
|
row.priority = getBypassZenMode(row.pkg, row.uid, row.topic);
|
||||||
row.sensitive = getSensitive(row.pkg, row.uid, row.topic);
|
row.sensitive = getSensitive(row.pkg, row.uid, row.topic);
|
||||||
row.banned = getNotificationsBanned(row.pkg, row.uid);
|
row.banned = getNotificationsBanned(row.pkg, row.uid);
|
||||||
|
row.importance = getImportance(row.pkg, row.uid, row.topic);
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,6 +129,25 @@ public class NotificationBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean setImportance(String pkg, int uid, Notification.Topic topic, int importance) {
|
||||||
|
try {
|
||||||
|
sINM.setTopicImportance(pkg, uid, topic, importance);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "Error calling NoMan", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getImportance(String pkg, int uid, Notification.Topic topic) {
|
||||||
|
try {
|
||||||
|
return sINM.getTopicImportance(pkg, uid, topic);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "Error calling NoMan", e);
|
||||||
|
return NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<Notification.Topic> getTopics(String pkg, int uid) {
|
public List<Notification.Topic> getTopics(String pkg, int uid) {
|
||||||
try {
|
try {
|
||||||
final ParceledListSlice<Notification.Topic> parceledList = sINM.getTopics(pkg, uid);
|
final ParceledListSlice<Notification.Topic> parceledList = sINM.getTopics(pkg, uid);
|
||||||
@@ -156,6 +176,7 @@ public class NotificationBackend {
|
|||||||
public Notification.Topic topic;
|
public Notification.Topic topic;
|
||||||
public boolean priority;
|
public boolean priority;
|
||||||
public boolean sensitive;
|
public boolean sensitive;
|
||||||
|
public int importance;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -30,14 +30,13 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.service.notification.NotificationListenerService;
|
||||||
import android.support.v14.preference.SwitchPreference;
|
import android.support.v14.preference.SwitchPreference;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
|
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@@ -50,10 +49,12 @@ public class TopicNotificationSettings extends SettingsPreferenceFragment {
|
|||||||
protected static final String ARG_PACKAGE_INFO = "arg_info";
|
protected static final String ARG_PACKAGE_INFO = "arg_info";
|
||||||
private static final String KEY_BYPASS_DND = "bypass_dnd";
|
private static final String KEY_BYPASS_DND = "bypass_dnd";
|
||||||
private static final String KEY_SENSITIVE = "sensitive";
|
private static final String KEY_SENSITIVE = "sensitive";
|
||||||
|
private static final String KEY_IMPORTANCE = "importance";
|
||||||
|
|
||||||
private final NotificationBackend mBackend = new NotificationBackend();
|
private final NotificationBackend mBackend = new NotificationBackend();
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private ImportanceSeekBarPreference mImportance;
|
||||||
private SwitchPreference mPriority;
|
private SwitchPreference mPriority;
|
||||||
private SwitchPreference mSensitive;
|
private SwitchPreference mSensitive;
|
||||||
private TopicRow mTopicRow;
|
private TopicRow mTopicRow;
|
||||||
@@ -122,11 +123,27 @@ public class TopicNotificationSettings extends SettingsPreferenceFragment {
|
|||||||
mIsSystemPackage = Utils.isSystemPackage(pm, info);
|
mIsSystemPackage = Utils.isSystemPackage(pm, info);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.topic_notification_settings);
|
addPreferencesFromResource(R.xml.topic_notification_settings);
|
||||||
|
mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE);
|
||||||
mPriority = (SwitchPreference) findPreference(KEY_BYPASS_DND);
|
mPriority = (SwitchPreference) findPreference(KEY_BYPASS_DND);
|
||||||
mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
|
mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
|
||||||
|
|
||||||
mTopicRow = mBackend.loadTopicRow(pm, info.applicationInfo, topic);
|
mTopicRow = mBackend.loadTopicRow(pm, info.applicationInfo, topic);
|
||||||
|
|
||||||
|
mImportance.setMax(4);
|
||||||
|
// TODO: stop defaulting to 'normal' in the UI when there are mocks for this scenario.
|
||||||
|
int importance =
|
||||||
|
mTopicRow.importance == NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED
|
||||||
|
? NotificationListenerService.Ranking.IMPORTANCE_DEFAULT
|
||||||
|
: mTopicRow.importance;
|
||||||
|
mImportance.setProgress(
|
||||||
|
importance + ImportanceSeekBarPreference.IMPORTANCE_PROGRESS_OFFSET);
|
||||||
|
mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onImportanceChanged(int progress) {
|
||||||
|
mBackend.setImportance(mTopicRow.pkg, mTopicRow.uid, mTopicRow.topic,
|
||||||
|
progress - ImportanceSeekBarPreference.IMPORTANCE_PROGRESS_OFFSET);
|
||||||
|
}
|
||||||
|
});
|
||||||
mPriority.setChecked(mTopicRow.priority);
|
mPriority.setChecked(mTopicRow.priority);
|
||||||
mSensitive.setChecked(mTopicRow.sensitive);
|
mSensitive.setChecked(mTopicRow.sensitive);
|
||||||
|
|
||||||
@@ -167,6 +184,7 @@ public class TopicNotificationSettings extends SettingsPreferenceFragment {
|
|||||||
setVisible(mPriority, mIsSystemPackage || !banned);
|
setVisible(mPriority, mIsSystemPackage || !banned);
|
||||||
setVisible(mSensitive, mIsSystemPackage || !banned && lockscreenSecure
|
setVisible(mSensitive, mIsSystemPackage || !banned && lockscreenSecure
|
||||||
&& lockscreenNotificationsEnabled && allowPrivate);
|
&& lockscreenNotificationsEnabled && allowPrivate);
|
||||||
|
setVisible(mImportance, !banned);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setVisible(Preference p, boolean visible) {
|
private void setVisible(Preference p, boolean visible) {
|
||||||
|
Reference in New Issue
Block a user