1 /* 2 * Copyright 2020 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 */ 16 17 package androidx.core.app; 18 19 import android.app.Notification; 20 import android.app.NotificationChannel; 21 import android.app.NotificationChannelGroup; 22 import android.content.Intent; 23 import android.media.AudioAttributes; 24 import android.net.Uri; 25 import android.os.Build; 26 import android.provider.Settings; 27 28 import androidx.annotation.RequiresApi; 29 import androidx.core.content.pm.ShortcutInfoCompat; 30 import androidx.core.util.Preconditions; 31 32 import org.jspecify.annotations.NonNull; 33 import org.jspecify.annotations.Nullable; 34 35 /** 36 * A representation of settings that apply to a collection of similarly themed notifications. 37 * 38 * Setters return {@code this} to allow chaining. 39 * 40 * This class doesn't do anything on older SDKs which don't support Notification Channels. 41 */ 42 public class NotificationChannelCompat { 43 /** 44 * The id of the default channel for an app. This id is reserved by the system. All 45 * notifications posted from apps targeting {@link android.os.Build.VERSION_CODES#N_MR1} or 46 * earlier without a notification channel specified are posted to this channel. 47 */ 48 public static final String DEFAULT_CHANNEL_ID = "miscellaneous"; 49 50 private static final boolean DEFAULT_SHOW_BADGE = true; 51 private static final int DEFAULT_LIGHT_COLOR = 0; 52 53 // These fields are settable through the builder 54 final @NonNull String mId; 55 CharSequence mName; 56 int mImportance; 57 String mDescription; 58 String mGroupId; 59 boolean mShowBadge = DEFAULT_SHOW_BADGE; 60 Uri mSound = Settings.System.DEFAULT_NOTIFICATION_URI; 61 AudioAttributes mAudioAttributes; 62 boolean mLights; 63 int mLightColor = DEFAULT_LIGHT_COLOR; 64 boolean mVibrationEnabled; 65 long[] mVibrationPattern; 66 String mParentId; 67 String mConversationId; 68 69 // These fields are read-only 70 private boolean mBypassDnd; 71 private int mLockscreenVisibility; 72 private boolean mCanBubble; 73 private boolean mImportantConversation; 74 75 /** 76 * Builder class for {@link NotificationChannelCompat} objects. 77 */ 78 public static class Builder { 79 private final NotificationChannelCompat mChannel; 80 81 /** 82 * Creates a notification channel builder. 83 * 84 * @param id The id of the channel. Must be unique per package. The value may be 85 * truncated if it is too long. 86 * @param importance The importance of the channel. This controls how interruptive 87 * notifications posted to this channel are. 88 */ Builder(@onNull String id, int importance)89 public Builder(@NonNull String id, int importance) { 90 mChannel = new NotificationChannelCompat(id, importance); 91 } 92 93 /** 94 * Sets the user visible name of this channel. 95 * 96 * You can rename this channel when the system locale changes by listening for the 97 * {@link Intent#ACTION_LOCALE_CHANGED} broadcast. 98 * 99 * <p>The recommended maximum length is 40 characters; the value may be truncated if it 100 * is too long. 101 */ setName(@ullable CharSequence name)102 public @NonNull Builder setName(@Nullable CharSequence name) { 103 mChannel.mName = name; 104 return this; 105 } 106 107 /** 108 * Sets the level of interruption of this notification channel. 109 * 110 * Only modifiable before the channel is submitted to 111 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}. 112 * 113 * @param importance the amount the user should be interrupted by notifications from this 114 * channel. 115 */ setImportance(int importance)116 public @NonNull Builder setImportance(int importance) { 117 mChannel.mImportance = importance; 118 return this; 119 } 120 121 /** 122 * Sets the user visible description of this channel. 123 * 124 * <p>The recommended maximum length is 300 characters; the value may be truncated if it is 125 * too long. 126 */ setDescription(@ullable String description)127 public @NonNull Builder setDescription(@Nullable String description) { 128 mChannel.mDescription = description; 129 return this; 130 } 131 132 /** 133 * Sets what group this channel belongs to. 134 * 135 * Group information is only used for presentation, not for behavior. 136 * 137 * Only modifiable before the channel is submitted to 138 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}, 139 * unless the channel is not currently part of a group. 140 * 141 * @param groupId the id of a group created by 142 * {@link NotificationManagerCompat#createNotificationChannelGroup}. 143 */ setGroup(@ullable String groupId)144 public @NonNull Builder setGroup(@Nullable String groupId) { 145 mChannel.mGroupId = groupId; 146 return this; 147 } 148 149 /** 150 * Sets whether notifications posted to this channel can appear as application icon badges 151 * in a Launcher. 152 * 153 * Only modifiable before the channel is submitted to 154 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}. 155 * 156 * @param showBadge true if badges should be allowed to be shown. 157 */ setShowBadge(boolean showBadge)158 public @NonNull Builder setShowBadge(boolean showBadge) { 159 mChannel.mShowBadge = showBadge; 160 return this; 161 } 162 163 /** 164 * Sets the sound that should be played for notifications posted to this channel and its 165 * audio attributes. Notification channels with an {@link #setImportance(int)} 166 * importance} of 167 * at least {@link NotificationManagerCompat#IMPORTANCE_DEFAULT} should have a sound. 168 * 169 * Only modifiable before the channel is submitted to 170 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}. 171 */ setSound(@ullable Uri sound, @Nullable AudioAttributes audioAttributes)172 public @NonNull Builder setSound(@Nullable Uri sound, 173 @Nullable AudioAttributes audioAttributes) { 174 mChannel.mSound = sound; 175 mChannel.mAudioAttributes = audioAttributes; 176 return this; 177 } 178 179 /** 180 * Sets whether notifications posted to this channel should display notification lights, 181 * on devices that support that feature. 182 * 183 * Only modifiable before the channel is submitted to 184 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}. 185 */ setLightsEnabled(boolean lights)186 public @NonNull Builder setLightsEnabled(boolean lights) { 187 mChannel.mLights = lights; 188 return this; 189 } 190 191 /** 192 * Sets the notification light color for notifications posted to this channel, if lights are 193 * {@link #setLightsEnabled(boolean) enabled} on this channel and the device supports that 194 * feature. 195 * 196 * Only modifiable before the channel is submitted to 197 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}. 198 */ setLightColor(int argb)199 public @NonNull Builder setLightColor(int argb) { 200 mChannel.mLightColor = argb; 201 return this; 202 } 203 204 /** 205 * Sets whether notification posted to this channel should vibrate. The vibration pattern 206 * can be set with {@link #setVibrationPattern(long[])}. 207 * 208 * Only modifiable before the channel is submitted to 209 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}. 210 */ setVibrationEnabled(boolean vibration)211 public @NonNull Builder setVibrationEnabled(boolean vibration) { 212 mChannel.mVibrationEnabled = vibration; 213 return this; 214 } 215 216 /** 217 * Sets the vibration pattern for notifications posted to this channel. If the provided 218 * pattern is valid (non-null, non-empty), will {@link #setVibrationEnabled(boolean)} enable 219 * vibration} as well. Otherwise, vibration will be disabled. 220 * 221 * Only modifiable before the channel is submitted to 222 * {@link NotificationManagerCompat#createNotificationChannel(NotificationChannelCompat)}. 223 */ setVibrationPattern(long @Nullable [] vibrationPattern)224 public @NonNull Builder setVibrationPattern(long @Nullable [] vibrationPattern) { 225 mChannel.mVibrationEnabled = vibrationPattern != null && vibrationPattern.length > 0; 226 mChannel.mVibrationPattern = vibrationPattern; 227 return this; 228 } 229 230 /** 231 * Sets this channel as being conversation-centric. Different settings and functionality may 232 * be exposed for conversation-centric channels. 233 * 234 * Calling this on SDKs that do not support conversations will have no effect on the 235 * built channel. As a result, this channel will not be linked to the channel with the 236 * parentChannelId. That means that this channel must be published to directly to be used; 237 * it cannot be published to by publishing to the parentChannelId with the shortcutId. 238 * 239 * @param parentChannelId The {@link #getId()} id} of the generic channel that notifications 240 * of this type would be posted to in absence of a specific 241 * conversation id. For example, if this channel represents 242 * 'Messages from Person A', the parent channel would be 'Messages.' 243 * @param conversationId The {@link ShortcutInfoCompat#getId()} of the shortcut 244 * representing this channel's conversation. 245 */ setConversationId(@onNull String parentChannelId, @NonNull String conversationId)246 public @NonNull Builder setConversationId(@NonNull String parentChannelId, 247 @NonNull String conversationId) { 248 if (Build.VERSION.SDK_INT >= 30) { 249 mChannel.mParentId = parentChannelId; 250 mChannel.mConversationId = conversationId; 251 } 252 return this; 253 } 254 255 /** 256 * Creates a {@link NotificationChannelCompat} instance. 257 */ build()258 public @NonNull NotificationChannelCompat build() { 259 return mChannel; 260 } 261 } 262 NotificationChannelCompat(@onNull String id, int importance)263 NotificationChannelCompat(@NonNull String id, int importance) { 264 mId = Preconditions.checkNotNull(id); 265 mImportance = importance; 266 if (Build.VERSION.SDK_INT >= 21) { 267 mAudioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT; 268 } 269 } 270 271 @RequiresApi(26) NotificationChannelCompat(@onNull NotificationChannel channel)272 NotificationChannelCompat(@NonNull NotificationChannel channel) { 273 this(Api26Impl.getId(channel), Api26Impl.getImportance(channel)); 274 // Populate all builder-editable fields 275 mName = Api26Impl.getName(channel); 276 mDescription = Api26Impl.getDescription(channel); 277 mGroupId = Api26Impl.getGroup(channel); 278 mShowBadge = Api26Impl.canShowBadge(channel); 279 mSound = Api26Impl.getSound(channel); 280 mAudioAttributes = Api26Impl.getAudioAttributes(channel); 281 mLights = Api26Impl.shouldShowLights(channel); 282 mLightColor = Api26Impl.getLightColor(channel); 283 mVibrationEnabled = Api26Impl.shouldVibrate(channel); 284 mVibrationPattern = Api26Impl.getVibrationPattern(channel); 285 if (Build.VERSION.SDK_INT >= 30) { 286 mParentId = Api30Impl.getParentChannelId(channel); 287 mConversationId = Api30Impl.getConversationId(channel); 288 } 289 // Populate all read-only fields 290 mBypassDnd = Api26Impl.canBypassDnd(channel); 291 mLockscreenVisibility = Api26Impl.getLockscreenVisibility(channel); 292 if (Build.VERSION.SDK_INT >= 29) { 293 mCanBubble = Api29Impl.canBubble(channel); 294 } 295 if (Build.VERSION.SDK_INT >= 30) { 296 mImportantConversation = Api30Impl.isImportantConversation(channel); 297 } 298 } 299 300 /** 301 * Gets the platform notification channel object. 302 * 303 * Returns {@code null} on older SDKs which don't support Notification Channels. 304 */ getNotificationChannel()305 NotificationChannel getNotificationChannel() { 306 if (Build.VERSION.SDK_INT < 26) { 307 return null; 308 } 309 NotificationChannel channel = Api26Impl.createNotificationChannel(mId, mName, mImportance); 310 Api26Impl.setDescription(channel, mDescription); 311 Api26Impl.setGroup(channel, mGroupId); 312 Api26Impl.setShowBadge(channel, mShowBadge); 313 Api26Impl.setSound(channel, mSound, mAudioAttributes); 314 Api26Impl.enableLights(channel, mLights); 315 Api26Impl.setLightColor(channel, mLightColor); 316 Api26Impl.setVibrationPattern(channel, mVibrationPattern); 317 Api26Impl.enableVibration(channel, mVibrationEnabled); 318 if (Build.VERSION.SDK_INT >= 30 && mParentId != null && mConversationId != null) { 319 Api30Impl.setConversationId(channel, mParentId, mConversationId); 320 } 321 return channel; 322 } 323 324 /** 325 * Creates a {@link Builder} instance with all the writeable property values of this instance. 326 */ toBuilder()327 public @NonNull Builder toBuilder() { 328 return new Builder(mId, mImportance) 329 .setName(mName) 330 .setDescription(mDescription) 331 .setGroup(mGroupId) 332 .setShowBadge(mShowBadge) 333 .setSound(mSound, mAudioAttributes) 334 .setLightsEnabled(mLights) 335 .setLightColor(mLightColor) 336 .setVibrationEnabled(mVibrationEnabled) 337 .setVibrationPattern(mVibrationPattern) 338 .setConversationId(mParentId, mConversationId); 339 } 340 341 /** 342 * Returns the id of this channel. 343 */ getId()344 public @NonNull String getId() { 345 return mId; 346 } 347 348 /** 349 * Returns the user visible name of this channel. 350 */ getName()351 public @Nullable CharSequence getName() { 352 return mName; 353 } 354 355 /** 356 * Returns the user visible description of this channel. 357 */ getDescription()358 public @Nullable String getDescription() { 359 return mDescription; 360 } 361 362 /** 363 * Returns the user specified importance e.g. {@link NotificationManagerCompat#IMPORTANCE_LOW} 364 * for notifications posted to this channel. Note: This value might be > 365 * {@link NotificationManagerCompat#IMPORTANCE_NONE}, but notifications posted to this channel 366 * will not be shown to the user if the parent {@link NotificationChannelGroup} or app is 367 * blocked. 368 * See {@link NotificationChannelGroup#isBlocked()} and 369 * {@link NotificationManagerCompat#areNotificationsEnabled()}. 370 */ getImportance()371 public int getImportance() { 372 return mImportance; 373 } 374 375 /** 376 * Returns the notification sound for this channel. 377 */ getSound()378 public @Nullable Uri getSound() { 379 return mSound; 380 } 381 382 /** 383 * Returns the audio attributes for sound played by notifications posted to this channel. 384 */ getAudioAttributes()385 public @Nullable AudioAttributes getAudioAttributes() { 386 return mAudioAttributes; 387 } 388 389 /** 390 * Returns whether notifications posted to this channel trigger notification lights. 391 */ shouldShowLights()392 public boolean shouldShowLights() { 393 return mLights; 394 } 395 396 /** 397 * Returns the notification light color for notifications posted to this channel. Irrelevant 398 * unless {@link #shouldShowLights()}. 399 */ getLightColor()400 public int getLightColor() { 401 return mLightColor; 402 } 403 404 /** 405 * Returns whether notifications posted to this channel always vibrate. 406 */ shouldVibrate()407 public boolean shouldVibrate() { 408 return mVibrationEnabled; 409 } 410 411 /** 412 * Returns the vibration pattern for notifications posted to this channel. Will be ignored if 413 * vibration is not enabled ({@link #shouldVibrate()}. 414 */ getVibrationPattern()415 public long @Nullable [] getVibrationPattern() { 416 return mVibrationPattern; 417 } 418 419 /** 420 * Returns whether notifications posted to this channel can appear as badges in a Launcher 421 * application. 422 * 423 * Note that badging may be disabled for other reasons. 424 */ canShowBadge()425 public boolean canShowBadge() { 426 return mShowBadge; 427 } 428 429 /** 430 * Returns what group this channel belongs to. 431 * 432 * This is used only for visually grouping channels in the UI. 433 */ getGroup()434 public @Nullable String getGroup() { 435 return mGroupId; 436 } 437 438 /** 439 * Returns the {@link #getId() id} of the parent notification channel to this channel, if it's 440 * a conversation related channel. 441 * See {@link Builder#setConversationId(String, String)}. 442 */ getParentChannelId()443 public @Nullable String getParentChannelId() { 444 return mParentId; 445 } 446 447 /** 448 * Returns the {@link ShortcutInfoCompat#getId() id} of the conversation backing this channel, 449 * if it's associated with a conversation. 450 * See {@link Builder#setConversationId(String, String)}. 451 */ getConversationId()452 public @Nullable String getConversationId() { 453 return mConversationId; 454 } 455 456 /** 457 * Whether or not notifications posted to this channel can bypass the Do Not Disturb 458 * {@link android.app.NotificationManager#INTERRUPTION_FILTER_PRIORITY} mode. 459 * 460 * <p>This is a read-only property which is only valid on instances fetched from the 461 * {@link NotificationManagerCompat}. 462 */ canBypassDnd()463 public boolean canBypassDnd() { 464 return mBypassDnd; 465 } 466 467 /** 468 * Returns whether or not notifications posted to this channel are shown on the lockscreen 469 * in full or redacted form. 470 * 471 * <p>This is a read-only property which is only valid on instances fetched from the 472 * {@link NotificationManagerCompat}. 473 */ 474 @NotificationCompat.NotificationVisibility getLockscreenVisibility()475 public int getLockscreenVisibility() { 476 return mLockscreenVisibility; 477 } 478 479 /** 480 * Returns whether notifications posted to this channel are allowed to display outside of the 481 * notification shade, in a floating window on top of other apps. 482 * 483 * <p>This is a read-only property which is only valid on instances fetched from the 484 * {@link NotificationManagerCompat}. 485 */ canBubble()486 public boolean canBubble() { 487 return mCanBubble; 488 } 489 490 /** 491 * Whether or not notifications in this conversation are considered important. 492 * 493 * <p>Important conversations may get special visual treatment, and might be able to bypass DND. 494 * 495 * <p>This is only valid for channels that represent conversations, that is, those with a valid 496 * {@link #getConversationId() conversation id}. 497 * 498 * <p>This is a read-only property which is only valid on instances fetched from the 499 * {@link NotificationManagerCompat}. 500 */ isImportantConversation()501 public boolean isImportantConversation() { 502 return mImportantConversation; 503 } 504 505 /** 506 * A class for wrapping calls to {@link NotificationChannel} methods which 507 * were added in API 26; these calls must be wrapped to avoid performance issues. 508 * See the UnsafeNewApiCall lint rule for more details. 509 */ 510 @RequiresApi(26) 511 static class Api26Impl { Api26Impl()512 private Api26Impl() { } 513 createNotificationChannel(String id, CharSequence name, int importance)514 static NotificationChannel createNotificationChannel(String id, CharSequence name, 515 int importance) { 516 return new NotificationChannel(id, name, importance); 517 } 518 getId(NotificationChannel notificationChannel)519 static String getId(NotificationChannel notificationChannel) { 520 return notificationChannel.getId(); 521 } 522 getImportance(NotificationChannel notificationChannel)523 static int getImportance(NotificationChannel notificationChannel) { 524 return notificationChannel.getImportance(); 525 } 526 getName(NotificationChannel notificationChannel)527 static CharSequence getName(NotificationChannel notificationChannel) { 528 return notificationChannel.getName(); 529 } 530 getDescription(NotificationChannel notificationChannel)531 static String getDescription(NotificationChannel notificationChannel) { 532 return notificationChannel.getDescription(); 533 } 534 setDescription(NotificationChannel notificationChannel, String description)535 static void setDescription(NotificationChannel notificationChannel, String description) { 536 notificationChannel.setDescription(description); 537 } 538 getGroup(NotificationChannel notificationChannel)539 static String getGroup(NotificationChannel notificationChannel) { 540 return notificationChannel.getGroup(); 541 } 542 setGroup(NotificationChannel notificationChannel, String groupId)543 static void setGroup(NotificationChannel notificationChannel, String groupId) { 544 notificationChannel.setGroup(groupId); 545 } 546 canShowBadge(NotificationChannel notificationChannel)547 static boolean canShowBadge(NotificationChannel notificationChannel) { 548 return notificationChannel.canShowBadge(); 549 } 550 setShowBadge(NotificationChannel notificationChannel, boolean showBadge)551 static void setShowBadge(NotificationChannel notificationChannel, boolean showBadge) { 552 notificationChannel.setShowBadge(showBadge); 553 } 554 getSound(NotificationChannel notificationChannel)555 static Uri getSound(NotificationChannel notificationChannel) { 556 return notificationChannel.getSound(); 557 } 558 setSound(NotificationChannel notificationChannel, Uri sound, AudioAttributes audioAttributes)559 static void setSound(NotificationChannel notificationChannel, Uri sound, 560 AudioAttributes audioAttributes) { 561 notificationChannel.setSound(sound, audioAttributes); 562 } 563 getAudioAttributes(NotificationChannel notificationChannel)564 static AudioAttributes getAudioAttributes(NotificationChannel notificationChannel) { 565 return notificationChannel.getAudioAttributes(); 566 } 567 shouldShowLights(NotificationChannel notificationChannel)568 static boolean shouldShowLights(NotificationChannel notificationChannel) { 569 return notificationChannel.shouldShowLights(); 570 } 571 enableLights(NotificationChannel notificationChannel, boolean lights)572 static void enableLights(NotificationChannel notificationChannel, boolean lights) { 573 notificationChannel.enableLights(lights); 574 } 575 getLightColor(NotificationChannel notificationChannel)576 static int getLightColor(NotificationChannel notificationChannel) { 577 return notificationChannel.getLightColor(); 578 } 579 setLightColor(NotificationChannel notificationChannel, int argb)580 static void setLightColor(NotificationChannel notificationChannel, int argb) { 581 notificationChannel.setLightColor(argb); 582 } 583 shouldVibrate(NotificationChannel notificationChannel)584 static boolean shouldVibrate(NotificationChannel notificationChannel) { 585 return notificationChannel.shouldVibrate(); 586 } 587 enableVibration(NotificationChannel notificationChannel, boolean vibration)588 static void enableVibration(NotificationChannel notificationChannel, boolean vibration) { 589 notificationChannel.enableVibration(vibration); 590 } 591 getVibrationPattern(NotificationChannel notificationChannel)592 static long[] getVibrationPattern(NotificationChannel notificationChannel) { 593 return notificationChannel.getVibrationPattern(); 594 } 595 setVibrationPattern(NotificationChannel notificationChannel, long[] vibrationPattern)596 static void setVibrationPattern(NotificationChannel notificationChannel, 597 long[] vibrationPattern) { 598 notificationChannel.setVibrationPattern(vibrationPattern); 599 } 600 canBypassDnd(NotificationChannel notificationChannel)601 static boolean canBypassDnd(NotificationChannel notificationChannel) { 602 return notificationChannel.canBypassDnd(); 603 } 604 getLockscreenVisibility(NotificationChannel notificationChannel)605 static int getLockscreenVisibility(NotificationChannel notificationChannel) { 606 return notificationChannel.getLockscreenVisibility(); 607 } 608 609 } 610 611 /** 612 * A class for wrapping calls to {@link NotificationChannel} methods which 613 * were added in API 29; these calls must be wrapped to avoid performance issues. 614 * See the UnsafeNewApiCall lint rule for more details. 615 */ 616 @RequiresApi(29) 617 static class Api29Impl { Api29Impl()618 private Api29Impl() { } 619 canBubble(NotificationChannel notificationChannel)620 static boolean canBubble(NotificationChannel notificationChannel) { 621 return notificationChannel.canBubble(); 622 } 623 } 624 625 /** 626 * A class for wrapping calls to {@link NotificationChannel} methods which 627 * were added in API 30; these calls must be wrapped to avoid performance issues. 628 * See the UnsafeNewApiCall lint rule for more details. 629 */ 630 @RequiresApi(30) 631 static class Api30Impl { Api30Impl()632 private Api30Impl() { } 633 getParentChannelId(NotificationChannel notificationChannel)634 static String getParentChannelId(NotificationChannel notificationChannel) { 635 return notificationChannel.getParentChannelId(); 636 } 637 getConversationId(NotificationChannel notificationChannel)638 static String getConversationId(NotificationChannel notificationChannel) { 639 return notificationChannel.getConversationId(); 640 } 641 setConversationId(NotificationChannel notificationChannel, String parentChannelId, String conversationId)642 static void setConversationId(NotificationChannel notificationChannel, 643 String parentChannelId, String conversationId) { 644 notificationChannel.setConversationId(parentChannelId, conversationId); 645 } 646 isImportantConversation(NotificationChannel notificationChannel)647 static boolean isImportantConversation(NotificationChannel notificationChannel) { 648 return notificationChannel.isImportantConversation(); 649 } 650 } 651 } 652