diff options
author | Tony Wickham <twickham@google.com> | 2017-01-20 09:38:25 -0800 |
---|---|---|
committer | Tony Wickham <twickham@google.com> | 2017-01-25 17:36:31 -0800 |
commit | 9438ed414fdabadb4cd09da184867b1c44b91095 (patch) | |
tree | 9d84de236a89cde247b9de8f11408e815e6d6702 /src/com/android/launcher3/badge | |
parent | f3d02e4716f89d14d9017851db9ad6141ad26875 (diff) | |
download | android_packages_apps_Trebuchet-9438ed414fdabadb4cd09da184867b1c44b91095.tar.gz android_packages_apps_Trebuchet-9438ed414fdabadb4cd09da184867b1c44b91095.tar.bz2 android_packages_apps_Trebuchet-9438ed414fdabadb4cd09da184867b1c44b91095.zip |
Add swipe-to-dismiss notifications in popup menu.
- Next secondary icon animates up to replace dismissed main notification
- Add padding around main notification so it always aligns with the
straight edges of the view (not the rounded corners); looks more
dismissable
- Notification view collapses as notifications are dismissed
- To mimic system notification behavior, we copy SwipeHelper,
FlingAnimationUtils, and Interpolators. We also apply elevation
to notifications and reveal a darker color beneath when dismissing.
Bug: 32410600
Change-Id: I9fbf10e73bb4996f17ef061c856efb013967d972
Diffstat (limited to 'src/com/android/launcher3/badge')
-rw-r--r-- | src/com/android/launcher3/badge/BadgeInfo.java | 1 | ||||
-rw-r--r-- | src/com/android/launcher3/badge/NotificationInfo.java | 82 | ||||
-rw-r--r-- | src/com/android/launcher3/badge/NotificationListener.java | 213 |
3 files changed, 1 insertions, 295 deletions
diff --git a/src/com/android/launcher3/badge/BadgeInfo.java b/src/com/android/launcher3/badge/BadgeInfo.java index 4255c5132..673c297dc 100644 --- a/src/com/android/launcher3/badge/BadgeInfo.java +++ b/src/com/android/launcher3/badge/BadgeInfo.java @@ -16,6 +16,7 @@ package com.android.launcher3.badge; +import com.android.launcher3.notification.NotificationInfo; import com.android.launcher3.util.PackageUserKey; import java.util.HashSet; diff --git a/src/com/android/launcher3/badge/NotificationInfo.java b/src/com/android/launcher3/badge/NotificationInfo.java deleted file mode 100644 index 51f6a4f3a..000000000 --- a/src/com/android/launcher3/badge/NotificationInfo.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.launcher3.badge; - -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; -import android.service.notification.StatusBarNotification; -import android.view.View; - -import com.android.launcher3.Launcher; -import com.android.launcher3.popup.PopupContainerWithArrow; -import com.android.launcher3.util.PackageUserKey; - -/** - * An object that contains relevant information from a {@link StatusBarNotification}. This should - * only be created when we need to show the notification contents on the UI; until then, a - * {@link com.android.launcher3.badge.BadgeInfo} with only the notification key should - * be passed around, and then this can be constructed using the StatusBarNotification from - * {@link NotificationListener#getNotificationsForKeys(String[])}. - */ -public class NotificationInfo implements View.OnClickListener { - - public final PackageUserKey packageUserKey; - public final String notificationKey; - public final CharSequence title; - public final CharSequence text; - public final Drawable iconDrawable; - public final PendingIntent intent; - public final boolean autoCancel; - - /** - * Extracts the data that we need from the StatusBarNotification. - */ - public NotificationInfo(Context context, StatusBarNotification notification) { - packageUserKey = PackageUserKey.fromNotification(notification); - notificationKey = notification.getKey(); - title = notification.getNotification().extras.getCharSequence(Notification.EXTRA_TITLE); - text = notification.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT); - Icon icon = notification.getNotification().getLargeIcon(); - if (icon == null) { - icon = notification.getNotification().getSmallIcon(); - iconDrawable = icon.loadDrawable(context); - iconDrawable.setTint(notification.getNotification().color); - } else { - iconDrawable = icon.loadDrawable(context); - } - intent = notification.getNotification().contentIntent; - autoCancel = (notification.getNotification().flags - & Notification.FLAG_AUTO_CANCEL) != 0; - } - - @Override - public void onClick(View view) { - final Launcher launcher = Launcher.getLauncher(view.getContext()); - try { - intent.send(); - } catch (PendingIntent.CanceledException e) { - e.printStackTrace(); - } - if (autoCancel) { - launcher.getPopupDataProvider().cancelNotification(notificationKey); - } - PopupContainerWithArrow.getOpen(launcher).close(true); - } -} diff --git a/src/com/android/launcher3/badge/NotificationListener.java b/src/com/android/launcher3/badge/NotificationListener.java deleted file mode 100644 index 1668a6267..000000000 --- a/src/com/android/launcher3/badge/NotificationListener.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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.launcher3.badge; - -import android.app.Notification; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.service.notification.NotificationListenerService; -import android.service.notification.StatusBarNotification; -import android.support.annotation.Nullable; -import android.support.v4.util.Pair; - -import com.android.launcher3.LauncherModel; -import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.util.PackageUserKey; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * A {@link NotificationListenerService} that sends updates to its - * {@link NotificationsChangedListener} when notifications are posted or canceled, - * as well and when this service first connects. An instance of NotificationListener, - * and its methods for getting notifications, can be obtained via {@link #getInstance()}. - */ -public class NotificationListener extends NotificationListenerService { - - private static final int MSG_NOTIFICATION_POSTED = 1; - private static final int MSG_NOTIFICATION_REMOVED = 2; - private static final int MSG_NOTIFICATION_FULL_REFRESH = 3; - - private static NotificationListener sNotificationListenerInstance = null; - private static NotificationsChangedListener sNotificationsChangedListener; - - private final Handler mWorkerHandler; - private final Handler mUiHandler; - - private Handler.Callback mWorkerCallback = new Handler.Callback() { - @Override - public boolean handleMessage(Message message) { - switch (message.what) { - case MSG_NOTIFICATION_POSTED: - mUiHandler.obtainMessage(message.what, message.obj).sendToTarget(); - break; - case MSG_NOTIFICATION_REMOVED: - mUiHandler.obtainMessage(message.what, message.obj).sendToTarget(); - break; - case MSG_NOTIFICATION_FULL_REFRESH: - final List<StatusBarNotification> activeNotifications - = filterNotifications(getActiveNotifications()); - mUiHandler.obtainMessage(message.what, activeNotifications).sendToTarget(); - break; - } - return true; - } - }; - - private Handler.Callback mUiCallback = new Handler.Callback() { - @Override - public boolean handleMessage(Message message) { - switch (message.what) { - case MSG_NOTIFICATION_POSTED: - if (sNotificationsChangedListener != null) { - Pair<PackageUserKey, String> pair - = (Pair<PackageUserKey, String>) message.obj; - sNotificationsChangedListener.onNotificationPosted(pair.first, pair.second); - } - break; - case MSG_NOTIFICATION_REMOVED: - if (sNotificationsChangedListener != null) { - Pair<PackageUserKey, String> pair - = (Pair<PackageUserKey, String>) message.obj; - sNotificationsChangedListener.onNotificationRemoved(pair.first, pair.second); - } - break; - case MSG_NOTIFICATION_FULL_REFRESH: - if (sNotificationsChangedListener != null) { - sNotificationsChangedListener.onNotificationFullRefresh( - (List<StatusBarNotification>) message.obj); - } - break; - } - return true; - } - }; - - public NotificationListener() { - super(); - mWorkerHandler = new Handler(LauncherModel.getWorkerLooper(), mWorkerCallback); - mUiHandler = new Handler(Looper.getMainLooper(), mUiCallback); - } - - public static @Nullable NotificationListener getInstance() { - return sNotificationListenerInstance; - } - - public static void setNotificationsChangedListener(NotificationsChangedListener listener) { - if (!FeatureFlags.BADGE_ICONS) { - return; - } - sNotificationsChangedListener = listener; - - NotificationListener notificationListener = getInstance(); - if (notificationListener != null) { - notificationListener.onNotificationFullRefresh(); - } - } - - public static void removeNotificationsChangedListener() { - sNotificationsChangedListener = null; - } - - @Override - public void onListenerConnected() { - super.onListenerConnected(); - sNotificationListenerInstance = this; - onNotificationFullRefresh(); - } - - private void onNotificationFullRefresh() { - mWorkerHandler.obtainMessage(MSG_NOTIFICATION_FULL_REFRESH).sendToTarget(); - } - - @Override - public void onListenerDisconnected() { - super.onListenerDisconnected(); - sNotificationListenerInstance = null; - } - - @Override - public void onNotificationPosted(final StatusBarNotification sbn) { - super.onNotificationPosted(sbn); - if (!shouldBeFilteredOut(sbn.getNotification())) { - Pair<PackageUserKey, String> packageUserKeyAndNotificationKey - = new Pair<>(PackageUserKey.fromNotification(sbn), sbn.getKey()); - mWorkerHandler.obtainMessage(MSG_NOTIFICATION_POSTED, packageUserKeyAndNotificationKey) - .sendToTarget(); - } - } - - @Override - public void onNotificationRemoved(final StatusBarNotification sbn) { - super.onNotificationRemoved(sbn); - if (!shouldBeFilteredOut(sbn.getNotification())) { - Pair<PackageUserKey, String> packageUserKeyAndNotificationKey - = new Pair<>(PackageUserKey.fromNotification(sbn), sbn.getKey()); - mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey) - .sendToTarget(); - } - } - - /** This makes a potentially expensive binder call and should be run on a background thread. */ - public List<StatusBarNotification> getNotificationsForKeys(String[] keys) { - StatusBarNotification[] notifications = NotificationListener.this - .getActiveNotifications(keys); - return notifications == null ? Collections.EMPTY_LIST : Arrays.asList(notifications); - } - - /** - * Filter out notifications that don't have an intent - * or are headers for grouped notifications. - * - * TODO: use the system concept of a badged notification instead - */ - private List<StatusBarNotification> filterNotifications( - StatusBarNotification[] notifications) { - if (notifications == null) return null; - Set<Integer> removedNotifications = new HashSet<>(); - for (int i = 0; i < notifications.length; i++) { - if (shouldBeFilteredOut(notifications[i].getNotification())) { - removedNotifications.add(i); - } - } - List<StatusBarNotification> filteredNotifications = new ArrayList<>( - notifications.length - removedNotifications.size()); - for (int i = 0; i < notifications.length; i++) { - if (!removedNotifications.contains(i)) { - filteredNotifications.add(notifications[i]); - } - } - return filteredNotifications; - } - - private boolean shouldBeFilteredOut(Notification notification) { - boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0; - return (notification.contentIntent == null || isGroupHeader); - } - - public interface NotificationsChangedListener { - void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey); - void onNotificationRemoved(PackageUserKey removedPackageUserKey, String notificationKey); - void onNotificationFullRefresh(List<StatusBarNotification> activeNotifications); - } -} |