1 package com.example.android.activenotifications;
2 /*
3 * Copyright 2015 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 
18 import android.app.Notification;
19 import android.app.NotificationManager;
20 import android.app.PendingIntent;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.service.notification.StatusBarNotification;
25 import android.support.v4.app.Fragment;
26 import android.support.v4.app.NotificationCompat;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.view.ViewGroup;
30 import android.widget.TextView;
31 
32 import com.example.android.common.logger.Log;
33 
34 /**
35  * A fragment that allows notifications to be enqueued.
36  */
37 public class ActiveNotificationsFragment extends Fragment {
38 
39     /**
40      * The request code can be any number as long as it doesn't match another request code used
41      * in the same app.
42      */
43     private static final int REQUEST_CODE = 2323;
44 
45     private static final String TAG = "ActiveNotificationsFragment";
46 
47     private static final String NOTIFICATION_GROUP =
48             "com.example.android.activenotifications.notification_type";
49 
50     private static final int NOTIFICATION_GROUP_SUMMARY_ID = 1;
51 
52     private NotificationManager mNotificationManager;
53 
54     private TextView mNumberOfNotifications;
55 
56     // Every notification needs a unique ID otherwise the previous one would be overwritten. This
57     // variable is incremented when used.
58     private static int sNotificationId = NOTIFICATION_GROUP_SUMMARY_ID + 1;
59 
60     private PendingIntent mDeletePendingIntent;
61 
62     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)63     public View onCreateView(LayoutInflater inflater, ViewGroup container,
64             Bundle savedInstanceState) {
65         return inflater.inflate(R.layout.fragment_notification_builder, container, false);
66     }
67 
68     @Override
onResume()69     public void onResume() {
70         super.onResume();
71         updateNumberOfNotifications();
72     }
73 
74     @Override
onViewCreated(View view, Bundle savedInstanceState)75     public void onViewCreated(View view, Bundle savedInstanceState) {
76         super.onViewCreated(view, savedInstanceState);
77         mNotificationManager = (NotificationManager) getActivity().getSystemService(
78                 Context.NOTIFICATION_SERVICE);
79         mNumberOfNotifications = (TextView) view.findViewById(R.id.number_of_notifications);
80 
81         // Supply actions to the button that is displayed on screen.
82         View.OnClickListener onClickListener = new View.OnClickListener() {
83             @Override
84             public void onClick(View v) {
85                 switch (v.getId()) {
86                     case R.id.add_notification: {
87                         addNotificationAndUpdateSummaries();
88                         break;
89                     }
90                 }
91             }
92         };
93         view.findViewById(R.id.add_notification).setOnClickListener(onClickListener);
94 
95         // [BEGIN create_pending_intent_for_deletion]
96         // Create a PendingIntent to be fired upon deletion of a Notification.
97         Intent deleteIntent = new Intent(ActiveNotificationsActivity.ACTION_NOTIFICATION_DELETE);
98         mDeletePendingIntent = PendingIntent.getBroadcast(getActivity(),
99                 REQUEST_CODE, deleteIntent, 0);
100         // [END create_pending_intent_for_deletion]
101     }
102 
103     /**
104      * Adds a new {@link Notification} with sample data and sends it to the system.
105      * Then updates the current number of displayed notifications for this application and
106      * creates a notification summary if more than one notification exists.
107      */
addNotificationAndUpdateSummaries()108     private void addNotificationAndUpdateSummaries() {
109         // [BEGIN create_notification]
110         // Create a Notification and notify the system.
111         final NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity())
112                 .setSmallIcon(R.mipmap.ic_notification)
113                 .setContentTitle(getString(R.string.app_name))
114                 .setContentText(getString(R.string.sample_notification_content))
115                 .setAutoCancel(true)
116                 .setDeleteIntent(mDeletePendingIntent)
117                 .setGroup(NOTIFICATION_GROUP);
118 
119         final Notification notification = builder.build();
120         mNotificationManager.notify(getNewNotificationId(), notification);
121         // [END create_notification]
122         Log.i(TAG, "Add a notification");
123 
124         updateNotificationSummary();
125         updateNumberOfNotifications();
126     }
127 
128     /**
129      * Adds/updates/removes the notification summary as necessary.
130      */
updateNotificationSummary()131     protected void updateNotificationSummary() {
132         int numberOfNotifications = getNumberOfNotifications();
133 
134         if (numberOfNotifications > 1) {
135             // Add/update the notification summary.
136             String notificationContent = getString(R.string.sample_notification_summary_content,
137                     numberOfNotifications);
138             final NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity())
139                     .setSmallIcon(R.mipmap.ic_notification)
140                     .setStyle(new NotificationCompat.BigTextStyle()
141                             .setSummaryText(notificationContent))
142                     .setGroup(NOTIFICATION_GROUP)
143                     .setGroupSummary(true);
144             final Notification notification = builder.build();
145             mNotificationManager.notify(NOTIFICATION_GROUP_SUMMARY_ID, notification);
146         } else {
147             // Remove the notification summary.
148             mNotificationManager.cancel(NOTIFICATION_GROUP_SUMMARY_ID);
149         }
150     }
151 
152     /**
153      * Requests the current number of notifications from the {@link NotificationManager} and
154      * display them to the user.
155      */
updateNumberOfNotifications()156     protected void updateNumberOfNotifications() {
157         final int numberOfNotifications = getNumberOfNotifications();
158         mNumberOfNotifications.setText(getString(R.string.active_notifications,
159                 numberOfNotifications));
160         Log.i(TAG, getString(R.string.active_notifications, numberOfNotifications));
161     }
162 
163     /**
164      * Retrieves a unique notification ID.
165      */
getNewNotificationId()166     public int getNewNotificationId() {
167         int notificationId = sNotificationId++;
168 
169         // Unlikely in the sample, but the int will overflow if used enough so we skip the summary
170         // ID. Most apps will prefer a more deterministic way of identifying an ID such as hashing
171         // the content of the notification.
172         if (notificationId == NOTIFICATION_GROUP_SUMMARY_ID) {
173             notificationId = sNotificationId++;
174         }
175         return notificationId;
176     }
177 
getNumberOfNotifications()178     private int getNumberOfNotifications() {
179         // [BEGIN get_active_notifications]
180         // Query the currently displayed notifications.
181         final StatusBarNotification[] activeNotifications = mNotificationManager
182                 .getActiveNotifications();
183         // [END get_active_notifications]
184 
185         // Since the notifications might include a summary notification remove it from the count if
186         // it is present.
187         for (StatusBarNotification notification : activeNotifications) {
188             if (notification.getId() == NOTIFICATION_GROUP_SUMMARY_ID) {
189                 return activeNotifications.length - 1;
190             }
191         }
192         return activeNotifications.length;
193     }
194 }
195