blob: 0fa3c7fa6492fe62b5412a6a3918b45529466263 [file] [log] [blame]
Julia Reynolds59e152e2017-01-25 17:42:53 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.app;
17
18import android.annotation.SystemApi;
Julia Reynolds005c8b92017-08-24 10:35:53 -040019import android.annotation.TestApi;
Julia Reynolds1d97e6a2017-03-13 15:05:40 -040020import android.content.Intent;
Julia Reynolds59e152e2017-01-25 17:42:53 -050021import android.os.Parcel;
22import android.os.Parcelable;
Julia Reynolds59e152e2017-01-25 17:42:53 -050023import android.text.TextUtils;
Kweku Adams62b42242017-09-25 12:54:02 -070024import android.util.proto.ProtoOutputStream;
Julia Reynolds59e152e2017-01-25 17:42:53 -050025
26import org.json.JSONException;
27import org.json.JSONObject;
Julia Reynolds005c8b92017-08-24 10:35:53 -040028import org.xmlpull.v1.XmlPullParser;
Julia Reynolds59e152e2017-01-25 17:42:53 -050029import org.xmlpull.v1.XmlSerializer;
30
31import java.io.IOException;
32import java.util.ArrayList;
Julia Reynolds59e152e2017-01-25 17:42:53 -050033import java.util.List;
34
35/**
36 * A grouping of related notification channels. e.g., channels that all belong to a single account.
37 */
38public final class NotificationChannelGroup implements Parcelable {
39
Julia Reynolds2c891c92017-03-17 14:23:47 -040040 /**
41 * The maximum length for text fields in a NotificationChannelGroup. Fields will be truncated at
42 * this limit.
43 */
44 private static final int MAX_TEXT_LENGTH = 1000;
45
Julia Reynolds59e152e2017-01-25 17:42:53 -050046 private static final String TAG_GROUP = "channelGroup";
47 private static final String ATT_NAME = "name";
Julia Reynolds005c8b92017-08-24 10:35:53 -040048 private static final String ATT_DESC = "desc";
Julia Reynolds59e152e2017-01-25 17:42:53 -050049 private static final String ATT_ID = "id";
Julia Reynolds005c8b92017-08-24 10:35:53 -040050 private static final String ATT_BLOCKED = "blocked";
Julia Reynolds59e152e2017-01-25 17:42:53 -050051
52 private final String mId;
53 private CharSequence mName;
Julia Reynolds005c8b92017-08-24 10:35:53 -040054 private String mDescription;
55 private boolean mBlocked;
Julia Reynolds59e152e2017-01-25 17:42:53 -050056 private List<NotificationChannel> mChannels = new ArrayList<>();
57
58 /**
Julia Reynolds1d97e6a2017-03-13 15:05:40 -040059 * Creates a notification channel group.
Julia Reynolds59e152e2017-01-25 17:42:53 -050060 *
Julia Reynolds2c891c92017-03-17 14:23:47 -040061 * @param id The id of the group. Must be unique per package. the value may be truncated if
62 * it is too long.
Julia Reynolds1d97e6a2017-03-13 15:05:40 -040063 * @param name The user visible name of the group. You can rename this group when the system
64 * locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED}
Julia Reynolds2c891c92017-03-17 14:23:47 -040065 * broadcast. <p>The recommended maximum length is 40 characters; the value may be
66 * truncated if it is too long.
Julia Reynolds59e152e2017-01-25 17:42:53 -050067 */
68 public NotificationChannelGroup(String id, CharSequence name) {
Julia Reynolds2c891c92017-03-17 14:23:47 -040069 this.mId = getTrimmedString(id);
70 this.mName = name != null ? getTrimmedString(name.toString()) : null;
Julia Reynolds59e152e2017-01-25 17:42:53 -050071 }
72
Julia Reynoldsbad42972017-04-25 13:52:49 -040073 /**
74 * @hide
75 */
Julia Reynolds59e152e2017-01-25 17:42:53 -050076 protected NotificationChannelGroup(Parcel in) {
77 if (in.readByte() != 0) {
78 mId = in.readString();
79 } else {
80 mId = null;
81 }
82 mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
Julia Reynolds005c8b92017-08-24 10:35:53 -040083 if (in.readByte() != 0) {
84 mDescription = in.readString();
85 } else {
86 mDescription = null;
87 }
Julia Reynoldsf02562a2017-01-26 13:33:56 -050088 in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader());
Julia Reynolds005c8b92017-08-24 10:35:53 -040089 mBlocked = in.readBoolean();
Julia Reynolds59e152e2017-01-25 17:42:53 -050090 }
91
Julia Reynolds2c891c92017-03-17 14:23:47 -040092 private String getTrimmedString(String input) {
93 if (input != null && input.length() > MAX_TEXT_LENGTH) {
94 return input.substring(0, MAX_TEXT_LENGTH);
95 }
96 return input;
97 }
98
Julia Reynolds59e152e2017-01-25 17:42:53 -050099 @Override
100 public void writeToParcel(Parcel dest, int flags) {
101 if (mId != null) {
102 dest.writeByte((byte) 1);
103 dest.writeString(mId);
104 } else {
105 dest.writeByte((byte) 0);
106 }
107 TextUtils.writeToParcel(mName, dest, flags);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400108 if (mDescription != null) {
109 dest.writeByte((byte) 1);
110 dest.writeString(mDescription);
111 } else {
112 dest.writeByte((byte) 0);
113 }
Julia Reynolds59e152e2017-01-25 17:42:53 -0500114 dest.writeParcelableList(mChannels, flags);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400115 dest.writeBoolean(mBlocked);
Julia Reynolds59e152e2017-01-25 17:42:53 -0500116 }
117
118 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400119 * Returns the id of this group.
Julia Reynolds59e152e2017-01-25 17:42:53 -0500120 */
121 public String getId() {
122 return mId;
123 }
124
125 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400126 * Returns the user visible name of this group.
Julia Reynolds59e152e2017-01-25 17:42:53 -0500127 */
128 public CharSequence getName() {
129 return mName;
130 }
131
Julia Reynolds399d9bf2017-08-11 12:52:14 -0400132 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400133 * Returns the user visible description of this group.
134 */
135 public String getDescription() {
136 return mDescription;
137 }
138
139 /**
Julia Reynolds59e152e2017-01-25 17:42:53 -0500140 * Returns the list of channels that belong to this group
Julia Reynolds59e152e2017-01-25 17:42:53 -0500141 */
Julia Reynolds59e152e2017-01-25 17:42:53 -0500142 public List<NotificationChannel> getChannels() {
143 return mChannels;
144 }
145
146 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400147 * Returns whether or not notifications posted to {@link NotificationChannel channels} belonging
Julia Reynolds8d2b0532018-03-29 15:44:13 -0400148 * to this group are blocked. This value is independent of
149 * {@link NotificationManager#areNotificationsEnabled()} and
150 * {@link NotificationChannel#getImportance()}.
Julia Reynolds005c8b92017-08-24 10:35:53 -0400151 */
152 public boolean isBlocked() {
153 return mBlocked;
154 }
155
156 /**
157 * Sets the user visible description of this group.
158 *
159 * <p>The recommended maximum length is 300 characters; the value may be truncated if it is too
160 * long.
161 */
162 public void setDescription(String description) {
163 mDescription = getTrimmedString(description);
164 }
165
166 /**
167 * @hide
168 */
169 @TestApi
170 public void setBlocked(boolean blocked) {
171 mBlocked = blocked;
172 }
173
174 /**
Julia Reynolds59e152e2017-01-25 17:42:53 -0500175 * @hide
176 */
Julia Reynolds59e152e2017-01-25 17:42:53 -0500177 public void addChannel(NotificationChannel channel) {
178 mChannels.add(channel);
179 }
180
181 /**
182 * @hide
183 */
Julia Reynolds005c8b92017-08-24 10:35:53 -0400184 public void setChannels(List<NotificationChannel> channels) {
185 mChannels = channels;
186 }
187
188 /**
189 * @hide
190 */
191 public void populateFromXml(XmlPullParser parser) {
192 // Name, id, and importance are set in the constructor.
193 setDescription(parser.getAttributeValue(null, ATT_DESC));
194 setBlocked(safeBool(parser, ATT_BLOCKED, false));
195 }
196
197 private static boolean safeBool(XmlPullParser parser, String att, boolean defValue) {
198 final String value = parser.getAttributeValue(null, att);
199 if (TextUtils.isEmpty(value)) return defValue;
200 return Boolean.parseBoolean(value);
201 }
202
203 /**
204 * @hide
205 */
Julia Reynolds59e152e2017-01-25 17:42:53 -0500206 public void writeXml(XmlSerializer out) throws IOException {
207 out.startTag(null, TAG_GROUP);
208
209 out.attribute(null, ATT_ID, getId());
Julia Reynoldsd5286842017-03-02 15:37:10 -0500210 if (getName() != null) {
211 out.attribute(null, ATT_NAME, getName().toString());
212 }
Julia Reynolds005c8b92017-08-24 10:35:53 -0400213 if (getDescription() != null) {
214 out.attribute(null, ATT_DESC, getDescription().toString());
215 }
216 out.attribute(null, ATT_BLOCKED, Boolean.toString(isBlocked()));
Julia Reynolds59e152e2017-01-25 17:42:53 -0500217
218 out.endTag(null, TAG_GROUP);
219 }
220
221 /**
222 * @hide
223 */
224 @SystemApi
225 public JSONObject toJson() throws JSONException {
226 JSONObject record = new JSONObject();
227 record.put(ATT_ID, getId());
228 record.put(ATT_NAME, getName());
Julia Reynolds005c8b92017-08-24 10:35:53 -0400229 record.put(ATT_DESC, getDescription());
230 record.put(ATT_BLOCKED, isBlocked());
Julia Reynolds59e152e2017-01-25 17:42:53 -0500231 return record;
232 }
233
234 public static final Creator<NotificationChannelGroup> CREATOR =
235 new Creator<NotificationChannelGroup>() {
236 @Override
237 public NotificationChannelGroup createFromParcel(Parcel in) {
238 return new NotificationChannelGroup(in);
239 }
240
241 @Override
242 public NotificationChannelGroup[] newArray(int size) {
243 return new NotificationChannelGroup[size];
244 }
245 };
246
247 @Override
248 public int describeContents() {
249 return 0;
250 }
251
252 @Override
253 public boolean equals(Object o) {
254 if (this == o) return true;
255 if (o == null || getClass() != o.getClass()) return false;
256
257 NotificationChannelGroup that = (NotificationChannelGroup) o;
258
Julia Reynolds005c8b92017-08-24 10:35:53 -0400259 if (isBlocked() != that.isBlocked()) return false;
Julia Reynolds59e152e2017-01-25 17:42:53 -0500260 if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
261 if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
262 return false;
263 }
Julia Reynolds005c8b92017-08-24 10:35:53 -0400264 if (getDescription() != null ? !getDescription().equals(that.getDescription())
265 : that.getDescription() != null) {
266 return false;
267 }
268 return getChannels() != null ? getChannels().equals(that.getChannels())
269 : that.getChannels() == null;
Julia Reynolds74856c42017-02-08 14:47:23 -0500270 }
271
272 @Override
Julia Reynolds59e152e2017-01-25 17:42:53 -0500273 public int hashCode() {
274 int result = getId() != null ? getId().hashCode() : 0;
275 result = 31 * result + (getName() != null ? getName().hashCode() : 0);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400276 result = 31 * result + (getDescription() != null ? getDescription().hashCode() : 0);
277 result = 31 * result + (isBlocked() ? 1 : 0);
278 result = 31 * result + (getChannels() != null ? getChannels().hashCode() : 0);
Julia Reynolds59e152e2017-01-25 17:42:53 -0500279 return result;
280 }
281
282 @Override
Julia Reynolds005c8b92017-08-24 10:35:53 -0400283 public NotificationChannelGroup clone() {
284 NotificationChannelGroup cloned = new NotificationChannelGroup(getId(), getName());
285 cloned.setDescription(getDescription());
286 cloned.setBlocked(isBlocked());
287 cloned.setChannels(getChannels());
288 return cloned;
289 }
290
291 @Override
Julia Reynolds59e152e2017-01-25 17:42:53 -0500292 public String toString() {
Julia Reynolds005c8b92017-08-24 10:35:53 -0400293 return "NotificationChannelGroup{"
294 + "mId='" + mId + '\''
295 + ", mName=" + mName
296 + ", mDescription=" + (!TextUtils.isEmpty(mDescription) ? "hasDescription " : "")
297 + ", mBlocked=" + mBlocked
298 + ", mChannels=" + mChannels
299 + '}';
Julia Reynolds59e152e2017-01-25 17:42:53 -0500300 }
Kweku Adams62b42242017-09-25 12:54:02 -0700301
302 /** @hide */
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800303 public void writeToProto(ProtoOutputStream proto, long fieldId) {
304 final long token = proto.start(fieldId);
305
Kweku Adams62b42242017-09-25 12:54:02 -0700306 proto.write(NotificationChannelGroupProto.ID, mId);
307 proto.write(NotificationChannelGroupProto.NAME, mName.toString());
308 proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription);
309 proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked);
310 for (NotificationChannel channel : mChannels) {
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800311 channel.writeToProto(proto, NotificationChannelGroupProto.CHANNELS);
Kweku Adams62b42242017-09-25 12:54:02 -0700312 }
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800313
314 proto.end(token);
Kweku Adams62b42242017-09-25 12:54:02 -0700315 }
Julia Reynolds59e152e2017-01-25 17:42:53 -0500316}