diff --git a/res/drawable/ic_history.xml b/res/drawable/ic_history.xml new file mode 100644 index 00000000000..c9f4524c78f --- /dev/null +++ b/res/drawable/ic_history.xml @@ -0,0 +1,25 @@ + + + + \ No newline at end of file diff --git a/res/layout/notification_history.xml b/res/layout/notification_history.xml index 91a59a8e8d0..a97afb66eee 100644 --- a/res/layout/notification_history.xml +++ b/res/layout/notification_history.xml @@ -19,141 +19,165 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:id="@+id/scroll" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:padding="16dp" + android:layout_height="match_parent" android:background="@*android:color/material_grey_50"> + - + + + + + + + + + + + + android:padding="16dp"> + - + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginBottom="28dp"> - - - - + + android:elevation="3dp" + android:background="@drawable/rounded_bg" + settings:layout_constraintHeight_max="200dp" + settings:layout_constrainedHeight="true"> - - + + + + - - + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginBottom="28dp"> + - - - - + + android:background="@drawable/rounded_bg"> + - - + + - - + android:layout_height="wrap_content" + android:orientation="vertical"> - - - + android:textAppearance="?android:attr/textAppearanceMedium" + android:paddingBottom="16dp" /> + + + diff --git a/res/layout/notification_history_app_layout.xml b/res/layout/notification_history_app_layout.xml index 6f26789e947..84fe91b9532 100644 --- a/res/layout/notification_history_app_layout.xml +++ b/res/layout/notification_history_app_layout.xml @@ -23,55 +23,76 @@ - - + + android:layout_height="wrap_content" + android:orientation="vertical"> + + + + + + - + + - + android:layout_height="wrap_content"> - - - + \ No newline at end of file diff --git a/res/layout/notification_history_log_row.xml b/res/layout/notification_history_log_row.xml index 4c38167faf0..748e1340c31 100644 --- a/res/layout/notification_history_log_row.xml +++ b/res/layout/notification_history_log_row.xml @@ -40,8 +40,8 @@ android:layout_centerVertical="true" android:ellipsize="end" android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textColor="@color/material_grey_900" + android:fontFamily="sans-serif-medium" + android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1" android:textAlignment="viewStart"/> - - diff --git a/res/layout/notification_sbn_log_row.xml b/res/layout/notification_sbn_log_row.xml index 3c51abd8e6f..39b918d623b 100644 --- a/res/layout/notification_sbn_log_row.xml +++ b/res/layout/notification_sbn_log_row.xml @@ -133,10 +133,4 @@ /> - - diff --git a/res/values/strings.xml b/res/values/strings.xml index dc1b1c65c7a..ceefd33e0c4 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -6183,6 +6183,12 @@ Snoozed Recently dismissed + + + %d notification + %d notifications + + Call ringtone & vibrate @@ -8034,6 +8040,15 @@ Notification history + + Turn on history + + + Turn off history + + + Notification history is turned off + Allow notification snoozing diff --git a/src/com/android/settings/notification/history/NotificationHistoryActivity.java b/src/com/android/settings/notification/history/NotificationHistoryActivity.java index 173508b4bec..7bd345f9eaf 100644 --- a/src/com/android/settings/notification/history/NotificationHistoryActivity.java +++ b/src/com/android/settings/notification/history/NotificationHistoryActivity.java @@ -16,15 +16,22 @@ package com.android.settings.notification.history; +import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED; + import android.app.Activity; import android.app.ActivityManager; import android.app.INotificationManager; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; +import android.database.ContentObserver; +import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; +import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.util.Log; @@ -36,11 +43,13 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; +import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; import com.android.settings.notification.NotificationBackend; +import com.android.settings.widget.SwitchBar; import java.util.Arrays; @@ -48,9 +57,13 @@ public class NotificationHistoryActivity extends Activity { private static String TAG = "NotifHistory"; + private ViewGroup mHistoryOn; + private ViewGroup mHistoryOff; private ViewGroup mTodayView; private ViewGroup mSnoozeView; private ViewGroup mDismissView; + + private SettingsObserver mSettingsObserver = new SettingsObserver(); private HistoryLoader mHistoryLoader; private INotificationManager mNm; private PackageManager mPm; @@ -77,9 +90,17 @@ public class NotificationHistoryActivity extends Activity { ImageView icon = viewForPackage.findViewById(R.id.icon); icon.setImageDrawable(nhp.icon); + TextView count = viewForPackage.findViewById(R.id.count); + count.setText(getResources().getQuantityString(R.plurals.notification_history_count, + nhp.notifications.size(), nhp.notifications.size())); + RecyclerView rv = viewForPackage.findViewById(R.id.notification_list); - rv.setLayoutManager(new LinearLayoutManager(this)); + LinearLayoutManager lm = new LinearLayoutManager(this); + rv.setLayoutManager(lm); rv.setAdapter(new NotificationHistoryAdapter()); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration( + rv.getContext(), lm.getOrientation()); + rv.addItemDecoration(dividerItemDecoration); ((NotificationHistoryAdapter) rv.getAdapter()).onRebuildComplete(nhp.notifications); mTodayView.addView(viewForPackage); } @@ -92,6 +113,8 @@ public class NotificationHistoryActivity extends Activity { mTodayView = findViewById(R.id.apps); mSnoozeView = findViewById(R.id.snoozed_list); mDismissView = findViewById(R.id.recently_dismissed_list); + mHistoryOff = findViewById(R.id.history_off); + mHistoryOn = findViewById(R.id.history_on); } @Override @@ -111,6 +134,9 @@ public class NotificationHistoryActivity extends Activity { } catch (RemoteException e) { Log.e(TAG, "Cannot register listener", e); } + mSettingsObserver.observe(); + + bindSwitch(); } @Override @@ -120,9 +146,87 @@ public class NotificationHistoryActivity extends Activity { } catch (RemoteException e) { Log.e(TAG, "Cannot unregister listener", e); } + mSettingsObserver.stopObserving(); super.onPause(); } + private void bindSwitch() { + SwitchBar bar = findViewById(R.id.switch_bar); + if (bar != null) { + bar.setSwitchBarText(R.string.notification_history_turn_off, + R.string.notification_history_turn_on); + bar.show(); + try { + bar.addOnSwitchChangeListener(mOnSwitchClickListener); + } catch (IllegalStateException e) { + // an exception is thrown if you try to add the listener twice + } + bar.setChecked(Settings.Secure.getInt(getContentResolver(), + NOTIFICATION_HISTORY_ENABLED, 0) == 1); + toggleViews(bar.isChecked()); + } + } + + private void toggleViews(boolean isChecked) { + if (isChecked) { + mHistoryOff.setVisibility(View.GONE); + mHistoryOn.setVisibility(View.VISIBLE); + } else { + mHistoryOn.setVisibility(View.GONE); + mHistoryOff.setVisibility(View.VISIBLE); + mTodayView.removeAllViews(); + } + } + + private void onHistoryEnabledChanged(boolean enabled) { + if (enabled) { + mHistoryLoader.load(mOnHistoryLoaderListener); + } + } + + final class SettingsObserver extends ContentObserver { + private final Uri NOTIFICATION_HISTORY_URI + = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_HISTORY_ENABLED); + + SettingsObserver() { + super(null); + } + + void observe() { + ContentResolver resolver = getContentResolver(); + resolver.registerContentObserver(NOTIFICATION_HISTORY_URI, + false, this, UserHandle.USER_ALL); + } + + void stopObserving() { + ContentResolver resolver = getContentResolver(); + resolver.unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + update(uri); + } + + public void update(Uri uri) { + ContentResolver resolver = getContentResolver(); + if (uri == null || NOTIFICATION_HISTORY_URI.equals(uri)) { + boolean historyEnabled = Settings.Secure.getInt(resolver, + Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0) + != 0; + onHistoryEnabledChanged(historyEnabled); + } + } + } + + private final SwitchBar.OnSwitchChangeListener mOnSwitchClickListener = + (switchView, isChecked) -> { + Settings.Secure.putInt(getContentResolver(), + NOTIFICATION_HISTORY_ENABLED, + isChecked ? 1 : 0); + toggleViews(isChecked); + }; + private final NotificationListenerService mListener = new NotificationListenerService() { @Override @@ -132,18 +236,26 @@ public class NotificationHistoryActivity extends Activity { mSnoozeView.setVisibility(View.GONE); } else { RecyclerView rv = mSnoozeView.findViewById(R.id.notification_list); - rv.setLayoutManager(new LinearLayoutManager(NotificationHistoryActivity.this)); + LinearLayoutManager lm = new LinearLayoutManager(NotificationHistoryActivity.this); + rv.setLayoutManager(lm); rv.setAdapter(new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm)); ((NotificationSbnAdapter) rv.getAdapter()).onRebuildComplete( Arrays.asList(snoozed)); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration( + rv.getContext(), lm.getOrientation()); + rv.addItemDecoration(dividerItemDecoration); } try { StatusBarNotification[] dismissed = mNm.getHistoricalNotifications( - NotificationHistoryActivity.this.getPackageName(), 10); + NotificationHistoryActivity.this.getPackageName(), 10, false); RecyclerView rv = mDismissView.findViewById(R.id.notification_list); - rv.setLayoutManager(new LinearLayoutManager(NotificationHistoryActivity.this)); + LinearLayoutManager lm = new LinearLayoutManager(NotificationHistoryActivity.this); + rv.setLayoutManager(lm); rv.setAdapter(new NotificationSbnAdapter(NotificationHistoryActivity.this, mPm)); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration( + rv.getContext(), lm.getOrientation()); + rv.addItemDecoration(dividerItemDecoration); ((NotificationSbnAdapter) rv.getAdapter()).onRebuildComplete( Arrays.asList(dismissed)); mDismissView.setVisibility(View.VISIBLE); diff --git a/src/com/android/settings/notification/history/NotificationHistoryAdapter.java b/src/com/android/settings/notification/history/NotificationHistoryAdapter.java index f87bb20373e..87804d5cca8 100644 --- a/src/com/android/settings/notification/history/NotificationHistoryAdapter.java +++ b/src/com/android/settings/notification/history/NotificationHistoryAdapter.java @@ -73,6 +73,7 @@ public class NotificationHistoryAdapter extends public void onRebuildComplete(List notifications) { mValues = notifications; + mValues.sort((o1, o2) -> Long.compare(o2.getPostedTimeMs(), o1.getPostedTimeMs())); notifyDataSetChanged(); } } diff --git a/src/com/android/settings/notification/history/NotificationStation.java b/src/com/android/settings/notification/history/NotificationStation.java index b147c087279..381fb4274fe 100644 --- a/src/com/android/settings/notification/history/NotificationStation.java +++ b/src/com/android/settings/notification/history/NotificationStation.java @@ -375,7 +375,7 @@ public class NotificationStation extends SettingsPreferenceFragment { StatusBarNotification[] active = mNoMan.getActiveNotifications( mContext.getPackageName()); StatusBarNotification[] dismissed = mNoMan.getHistoricalNotifications( - mContext.getPackageName(), 50); + mContext.getPackageName(), 50, false); List list = new ArrayList<>(active.length + dismissed.length);