이전에 알림의 채널에 관련돼서 포스팅을 했지만 알림에 관해서는 정리를 안 한 것 같아 알림 기능을 정리해 볼까 합니다.
알림은 이러한 구조로 구성됩니다.
NotificationManager : 알림을 시스템에 발생시키는 SystemService
Notification : 알림 구성 정보를 가지는 객체
NotificationCompat.Builder : 알림을 다양한 정보로 생성
NotificationChannel : 알림의 관리 단위(Android Oreo에서 추가)
이제 위 구조들을 이용하여 알림을 생성시켜 봅시다.
1. 처음에는 NotificationManager를 안드로이드에서 받아 와야 합니다.
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
2 - 1. 해당 안드로이드의 버전이 오레오 이상인 경우 NotificationChannel을 만들어 준다음 NotificationManager에 등록을 해줘야 합니다.
companion object {
private const val CHANNEL_ID = "default"
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Android 8.0
val channel = NotificationChannel(
CHANNEL_ID, "default channel",
NotificationManager.IMPORTANCE_DEFAULT
).apply {
description = "description text of this channel."
setShowBadge(true)
}
// 채널을 NotificationManager에 등록
manager.createNotificationChannel(channel)
}
이 코드들을 뜯어봅시다
/**
* Creates a notification channel.
* 알림 채널을 생성합니다.
*
* @param id The id of the channel. Must be unique per package. The value may be truncated if
* it is too long.
* id 채널의 ID입니다. 패키지별로 고유해야 합니다. 값이 너무 길면 잘릴 수 있습니다.
*
* @param name The user visible name of the channel. You can rename this channel when the system
* locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED}
* broadcast. The recommended maximum length is 40 characters; the value may be
* truncated if it is too long.
* 사용자에게 표시되는 채널 이름입니다.
* Intent.ACTION_LOCALE_CHANGED 브로드캐스트를 수신하여 시스템 로캘이 변경되면 이 채널의 이름을 바꿀 수 있습니다.
* 권장되는 최대 길이는 40자입니다.
* 값이 너무 길면 잘릴 수 있습니다.
*
* @param importance The importance of the channel. This controls how interruptive notifications
* posted to this channel are.
* 채널의 중요성. 이는 이 채널에 방해가 되는 알림이 게시되는 방식을 제어합니다.
*/
public NotificationChannel(String id, CharSequence name, @Importance int importance) {
this.mId = getTrimmedString(id);
this.mName = name != null ? getTrimmedString(name.toString()) : null;
this.mImportance = importance;
}
val channel = NotificationChannel(
CHANNEL_ID, "default channel",
NotificationManager.IMPORTANCE_DEFAULT
)
해당 함수는 Notification의 생성자입니다. 여기 유심히 봐야 할 부분은 중요도입니다.
/**
* Value signifying that the user has not expressed an importance.
*
* This value is for persisting preferences, and should never be associated with
* an actual notification.
* 사용자가 중요도를 표현하지 않았음을 나타내는 값입니다.
* 이 값은 기본 설정을 유지하기 위한 것이며 실제 알림과 연결되어서는 안 됩니다.
*/
public static final int IMPORTANCE_UNSPECIFIED = -1000;
/**
* A notification with no importance: does not show in the shade.
* 중요하지 않은 알림: 셰이드(상태바)에 표시되지 않습니다.
*/
public static final int IMPORTANCE_NONE = 0;
/**
* Min notification importance: only shows in the shade, below the fold. This should
* not be used with {@link Service#startForeground(int, Notification) Service.startForeground}
* since a foreground service is supposed to be something the user cares about so it does
* not make semantic sense to mark its notification as minimum importance. If you do this
* as of Android version {@link android.os.Build.VERSION_CODES#O}, the system will show
* a higher-priority notification about your app running in the background.
* 최소 알림 중요도: 스크롤 없이 볼 수 있는 부분의 셰이드(상태바)에만 표시됩니다.
* 포그라운드 서비스는 사용자가 관심을 갖는 것으로 간주되므로 알림을 최소 중요도로 표시하는 것은 의미상
* 의미가 없으므로 Service.startForeground와 함께 사용하면 안 됩니다. Android 버전 Build.VERSION_CODES.O부터
* 이 작업을 수행하면 시스템은 백그라운드에서 실행 중인 앱에 대해 더 높은 우선순위의 알림을 표시합니다.
*/
public static final int IMPORTANCE_MIN = 1;
/**
* Low notification importance: Shows in the shade, and potentially in the status bar
* (see {@link #shouldHideSilentStatusBarIcons()}), but is not audibly intrusive.
* 낮은 알림 중요도: 그늘에 표시되고 잠재적으로 상태 표시줄에 표시되지만
* ( shouldHideSilentStatusBarIcons() 참조) 청각적으로 방해가 되지는 않습니다.
*/
public static final int IMPORTANCE_LOW = 2;
/**
* Default notification importance: shows everywhere, makes noise, but does not visually
* intrude.
* 기본 알림 중요도: 모든 곳에 표시되고 소음이 발생하지만 시각적으로 방해되지 않습니다.
*/
public static final int IMPORTANCE_DEFAULT = 3;
/**
* Higher notification importance: shows everywhere, makes noise and peeks. May use full screen
* intents.
* 더 높은 알림 중요성: 모든 곳에 표시되고 소음이 발생하며 엿볼 수 있습니다. 전체 화면 의도를 사용할 수 있습니다.
*/
public static final int IMPORTANCE_HIGH = 4;
/**
* Unused.
* 사용안함
*/
public static final int IMPORTANCE_MAX = 5;
중요도 상수 | 설명 |
NotificationManager.IMPORTANCE_HIGH | 긴급 상황으로 알림음이 울리며 헤드업으로 표시 |
NotificationManager.IMPORTANCE_DEFAULT | 높은 중요도이며 알림음이 울림 |
NotificationManager.IMPORTANCE_LOW | 중간 중요도이며 알림음이 울리지 않음 |
NotificationManager. IMPORTANCE_MIN | 낮은 중요도이며 알림음도 없고 상태 바에도 표시되지 않음 |
사실상 위 4개만 쓰입니다.
이렇게 채널을 만들었다면 속성을 지정할 수 있습니다.
/**
* Allows users to block notifications sent through this channel, if this channel belongs to
* a package that otherwise would have notifications "fixed" as enabled.
*
* If the channel does not belong to a package that has a fixed notification permission, this
* method does nothing, since such channels are blockable by default and cannot be set to be
* unblockable.
* @param blockable if {@code true}, allows users to block notifications on this channel.
*/
/*
* 이 채널이 알림이 활성화된 패키지에 속해 있는 경우 사용자가 이 채널을 통해 전송된 알림을 차단할 수
* 있도록 허용합니다. 채널이 고정 알림 권한이 있는 패키지에 속하지 않는 경우 해당 채널은 기본적으로
* 차단 가능하고 차단 해제되도록 설정할 수 없으므로 이 메서드는 아무 작업도 수행하지 않습니다.
* 매개변수:
* blockable – true인 경우 사용자가 이 채널의 알림을 차단할 수 있습니다.
*/
public void setBlockable(boolean blockable) {
mBlockableSystem = blockable;
}
// Modifiable by apps post channel creation
// 채널 생성 후 앱에서 수정 가능
setBlockable이라는 알림 채널의 차단 관련 함수입니다.
/**
* Sets the user visible name of this channel.
*
* <p>The recommended maximum length is 40 characters; the value may be truncated if it is too
* long.
*/
/*
* 이 채널의 사용자 표시 이름을 설정합니다.
* 권장되는 최대 길이는 40자입니다. 값이 너무 길면 잘릴 수 있습니다.
*/
public void setName(CharSequence name) {
mName = name != null ? getTrimmedString(name.toString()) : null;
}
setName이라는 이름을 지정할 수 있는 함수입니다.
/**
* Sets the user visible description of this channel.
*
* <p>The recommended maximum length is 300 characters; the value may be truncated if it is too
* long.
*/
/*
* 이 채널에 대한 사용자 표시 설명을 설정합니다.
* 권장되는 최대 길이는 300자입니다. 값이 너무 길면 잘릴 수 있습니다.
*/
public void setDescription(String description) {
mDesc = getTrimmedString(description);
}
setDescription이라는 설명을 추가할 수 있는 함수입니다.
/**
* Sets what group this channel belongs to.
*
* Group information is only used for presentation, not for behavior.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}, unless the
* channel is not currently part of a group.
*
* @param groupId the id of a group created by
* {@link NotificationManager#createNotificationChannelGroup(NotificationChannelGroup)}.
*/
/*
* 이 채널이 속한 그룹을 설정합니다.
* 그룹 정보는 프레젠테이션에만 사용되며 행동에는 사용되지 않습니다.
* 채널이 현재 그룹의 일부가 아닌 경우 채널이 NotificationManager.createNotificationChannel(NotificationChannel)
* 에 제출되기 전에만 수정할 수 있습니다.
* 매개변수:
* groupId – NotificationManager.createNotificationChannelGroup(NotificationChannelGroup)
* 에 의해 생성된 그룹의 ID입니다.
*/
public void setGroup(String groupId) {
this.mGroup = groupId;
}
setGroup이라는 그룹을 설정할 수 있는 함수입니다. 여기서 보이는 그룹은 설정창에서 볼 수 있는 그룹이며 매개변수로 받는 groupId는 NotificationManager.createNotificationChannelGroup(NotificationChannelGroup)으로 등록한 그룹을 넣어줘야 합니다.
/**
* Creates a group container for {@link NotificationChannel} objects.
*
* This can be used to rename an existing group.
* <p>
* Group information is only used for presentation, not for behavior. Groups are optional
* for channels, and you can have a mix of channels that belong to groups and channels
* that do not.
* </p>
* <p>
* For example, if your application supports multiple accounts, and those accounts will
* have similar channels, you can create a group for each account with account specific
* labels instead of appending account information to each channel's label.
* </p>
*
* @param group The group to create
*/
/*
* NotificationChannel 개체에 대한 그룹 컨테이너를 만듭니다.
* 기존 그룹의 이름을 바꾸는 데 사용할 수 있습니다.
* 그룹 정보는 프레젠테이션에만 사용되며 행동에는 사용되지 않습니다.
* 그룹은 채널에 대한 선택 사항이며, 그룹에 속하는 채널과 그렇지 않은 채널을 혼합할 수 있습니다.
* 예를 들어 애플리케이션이 여러 계정을 지원하고 해당 계정에 유사한 채널이 있는 경우 각 채널의
* 라벨에 계정 정보를 추가하는 대신 계정별 라벨을 사용하여 각 계정에 대한 그룹을 생성할 수 있습니다.
* 매개변수: group – 생성할 그룹
*/
public void createNotificationChannelGroup(@NonNull NotificationChannelGroup group) {
createNotificationChannelGroups(Arrays.asList(group));
}
// The id of the group.
val groupId = "my_group_01"
// The user-visible name of the group.
val groupName = getString(R.string.group_name)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannelGroup(NotificationChannelGroup(groupId, groupName))
NotificationChannelGroup 같은 경우 위의 코드처럼 id와 이름으로 만들 수 있습니다.
위처럼 아무것도 설정을 안 한다면 디폴트로 나오고 그룹을 지정한다면 Personal이나 Work같이 그룹으로 묶여 있을 것입니다.
/**
* Sets whether notifications posted to this channel can appear as application icon badges
* in a Launcher.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*
* @param showBadge true if badges should be allowed to be shown.
*/
/*
* 이 채널에 게시된 알림이 실행기에서 애플리케이션 아이콘 배지로 표시될 수 있는지 여부를 설정합니다.
* 채널이 NotificationManager.createNotificationChannel(NotificationChannel)에 제출되기 전에만
* 수정할 수 있습니다.
* 매개변수:
* showBadge – 배지 표시를 허용해야 하는 경우 true입니다.
*/
public void setShowBadge(boolean showBadge) {
this.mShowBadge = showBadge;
}
setShowBadge라는 함수로 홈 화면의 아이콘에 배지 아이콘 출력 여부를 표시할 수 있습니다.
/**
* Sets the sound that should be played for notifications posted to this channel and its
* audio attributes. Notification channels with an {@link #getImportance() importance} of at
* least {@link NotificationManager#IMPORTANCE_DEFAULT} should have a sound.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*/
/* 이 채널에 게시된 알림에 대해 재생되어야 하는 사운드와 해당 오디오 속성을 설정합니다.
* 중요도가 최소한NotificationManager.IMPORTANCE_DEFAULT인 알림 채널에는 소리가 있어야 합니다.
* 채널이 NotificationManager.createNotificationChannel(NotificationChannel)에 제출되기 전에만
* 수정할 수 있습니다.
*/
public void setSound(Uri sound, AudioAttributes audioAttributes) {
this.mSound = sound;
this.mAudioAttributes = audioAttributes;
}
val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val audioAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build()
setSound(uri, audioAttributes)
setSound라는 함수로 해당채널에서 생기는 알람들의 소리를 지정할 수 있습니다. 예를 들어 카톡 같은 소리를 이렇게 설정할 수 있습니다.
/**
* Sets whether notifications posted to this channel should display notification lights,
* on devices that support that feature.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*/
/*
* 이 채널에 게시된 알림이 해당 기능을 지원하는 장치에 알림 표시등을 표시해야 하는지 여부를 설정합니다.
* 채널이 NotificationManager.createNotificationChannel(NotificationChannel)에 제출되기 전에만
* 수정할 수 있습니다.
*/
public void enableLights(boolean lights) {
this.mLights = lights;
}
/**
* Sets the notification light color for notifications posted to this channel, if lights are
* {@link #enableLights(boolean) enabled} on this channel and the device supports that feature.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*/
/*
* 이 채널에 조명이 활성화되어 있고 장치가 해당 기능을 지원하는 경우 이 채널에 게시된 알림에 대한
* 알림 조명 색상을 설정합니다.
* 채널이 NotificationManager.createNotificationChannel(NotificationChannel)에 제출되기 전에만
* 수정할 수 있습니다.
*/
public void setLightColor(int argb) {
this.mLightColor = argb;
}
enableLights라는 함수를 이용해서 빛을 내는 기능이 가능하는 기기의 경우 해당 기능을 사용할 것인지를 정할 수 있습니다. setLightColor라는 함수로 색상을 설정할 수도 있습니다.
/**
* Sets whether notification posted to this channel should vibrate. The vibration pattern can
* be set with {@link #setVibrationPattern(long[])}.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*/
/*
* 이 채널에 게시된 알림을 진동할지 여부를 설정합니다. 진동 패턴은 setVibrationPattern(long[])
* 으로 설정할 수 있습니다. 채널이 NotificationManager.createNotificationChannel(NotificationChannel)
* 에 제출되기 전에만 수정할 수 있습니다.
*/
public void enableVibration(boolean vibration) {
this.mVibrationEnabled = vibration;
}
/**
* Sets the vibration pattern for notifications posted to this channel. If the provided
* pattern is valid (non-null, non-empty), will {@link #enableVibration(boolean)} enable
* vibration} as well. Otherwise, vibration will be disabled.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*/
/*
* 이 채널에 게시되는 알림의 진동 패턴을 설정합니다. 제공된 패턴이 유효한 경우
* (null이 아님, 비어 있지 않음), 활성화(boolean) 진동 활성화}도 수행됩니다.
* 그렇지 않으면 진동이 비활성화됩니다. 채널이 NotificationManager.createNotificationChannel(NotificationChannel)
* 에 제출되기 전에만 수정할 수 있습니다.
*/
public void setVibrationPattern(long[] vibrationPattern) {
this.mVibrationEnabled = vibrationPattern != null && vibrationPattern.length > 0;
this.mVibration = vibrationPattern;
}
enableVibration라는 함수로 채널에 생기는 알림들의 진동여부를 지정할 수 있으며 setVibrationPattern라는 함수를 통해 바이브레이션 패턴을 지정할 수도 있습니다.
/**
* Sets the level of interruption of this notification channel.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#createNotificationChannel(NotificationChannel)}.
*
* @param importance the amount the user should be interrupted by
* notifications from this channel.
*/
public void setImportance(@Importance int importance) {
this.mImportance = importance;
}
// Modifiable by a notification ranker.
setImportance함수로 중요도를 바꿀 수도 있습니다.
/**
* Sets whether or not notifications posted to this channel can interrupt the user in
* {@link android.app.NotificationManager.Policy#INTERRUPTION_FILTER_PRIORITY} mode.
*
* Only modifiable by the system and notification ranker.
*/
/*
* 이 채널에 게시된 알림이 android.app.NotificationManager.Policy.INTERRUPTION_FILTER_PRIORITY
* 모드에서 사용자를 방해할 수 있는지 여부를 설정합니다. 시스템 및 알림 순위자에 의해서만 수정 가능합니다.
*/
public void setBypassDnd(boolean bypassDnd) {
this.mBypassDnd = bypassDnd;
}
android.app.NotificationManager.Policy.INTERRUPTION_FILTER_PRIORITY 모드에서 알림이 나올지를 설정할 수 있습니다.
/**
* Sets whether notifications posted to this channel appear on the lockscreen or not, and if so,
* whether they appear in a redacted form. See e.g. {@link Notification#VISIBILITY_SECRET}.
*
* Only modifiable by the system and notification ranker.
*/
/*
* 이 채널에 게시된 알림이 잠금 화면에 표시되는지 여부, 표시되는 경우 수정된 형식으로 표시되는지
* 여부를 설정합니다. 예를 들어 참조하십시오. 알림.VISIBILITY_SECRET. 시스템 및 알림 순위자에
* 의해서만 수정 가능
*/
public void setLockscreenVisibility(int lockscreenVisibility) {
this.mLockscreenVisibility = lockscreenVisibility;
}
/**
* Notification visibility: Show this notification in its entirety on all lockscreens.
* 알림 가시성: 모든 잠금 화면에 이 알림 전체를 표시합니다.
* {@see #visibility}
*/
public static final int VISIBILITY_PUBLIC = 1;
/**
* Notification visibility: Show this notification on all lockscreens, but conceal sensitive or
* private information on secure lockscreens.
* 알림 가시성: 모든 잠금 화면에 이 알림을 표시하지만 보안 잠금 화면에서는 민감한 정보나 개인 정보를 숨깁니다.
* {@see #visibility}
*/
public static final int VISIBILITY_PRIVATE = 0;
/**
* Notification visibility: Do not reveal any part of this notification on a secure lockscreen.
* 알림 가시성: 보안 잠금 화면에서 이 알림의 어떤 부분도 공개하지 마세요.
* {@see #visibility}
*/
public static final int VISIBILITY_SECRET = -1;
잠금화면일 때 알림을 표시할 것인지를 설정할 수 있습니다
이렇게 설정들을 지정하였다면 채널을 등록합니다.
/**
* Creates a notification channel that notifications can be posted to.
*
* This can also be used to restore a deleted channel and to update an existing channel's
* name, description, group, and/or importance.
*
* <p>The name and description should only be changed if the locale changes
* or in response to the user renaming this channel. For example, if a user has a channel
* named 'Messages' and the user changes their locale, this channel's name should be updated
* with the translation of 'Messages' in the new locale.
*
* <p>The importance of an existing channel will only be changed if the new importance is lower
* than the current value and the user has not altered any settings on this channel.
*
* <p>The group an existing channel will only be changed if the channel does not already
* belong to a group.
*
* All other fields are ignored for channels that already exist.
*
* @param channel the channel to create. Note that the created channel may differ from this
* value. If the provided channel is malformed, a RemoteException will be
* thrown.
*/
/*
* 알림을 게시할 수 있는 알림 채널을 만듭니다. 삭제된 채널을 복원하고 기존 채널의 이름, 설명, 그룹
* 및/또는 중요도를 업데이트하는 데에도 사용할 수 있습니다.
* 이름과 설명은 로캘이 변경되거나 사용자가 이 채널 이름을 바꾸는 경우에만 변경해야 합니다.
* 예를 들어, 사용자에게 '메시지'라는 채널이 있고 사용자가 로케일을 변경한 경우 이 채널의 이름은
* 새 로케일의 '메시지' 번역으로 업데이트되어야 합니다.
* 기존 채널의 중요도는 새 중요도가 현재 값보다 낮고 사용자가 이 채널의 설정을 변경하지 않은 경우에만 변경됩니다.
* 기존 채널의 그룹은 채널이 아직 그룹에 속하지 않은 경우에만 변경됩니다. 이미 존재하는 채널의 경우 다른 모든
* 필드는 무시됩니다.
* 매개변수:
* 채널 – 생성할 채널입니다. 생성된 채널은 이 값과 다를 수 있으니 참고하세요. 제공된 채널의 형식이 잘못된 경우 RemoteException이 발생합니다.
*/
public void createNotificationChannel(@NonNull NotificationChannel channel) {
createNotificationChannels(Arrays.asList(channel));
}
manager.createNotificationChannel(channel)
2 - 2. 알림을 생성시킬 빌더(NotificationCompat.Builder)를 구현
/**
* Constructor.
*
* Automatically sets the when field to {@link System#currentTimeMillis()
* System.currentTimeMillis()} and the audio stream to the
* {@link Notification#STREAM_DEFAULT}.
*
* @param context A {@link Context} that will be used to construct the
* RemoteViews. The Context will not be held past the lifetime of this
* Builder object.
* @param channelId The constructed Notification will be posted on this
* NotificationChannel.
*/
@SuppressWarnings("deprecation")
public Builder(@NonNull Context context, @NonNull String channelId) {
mContext = context;
mChannelId = channelId;
// Set defaults to match the defaults of a Notification
mNotification.when = System.currentTimeMillis();
mNotification.audioStreamType = Notification.STREAM_DEFAULT;
mPriority = PRIORITY_DEFAULT;
mPeople = new ArrayList<>();
mAllowSystemGeneratedContextualActions = true;
}
/**
* @deprecated use {@code Builder(Context, String)} instead. All posted notifications must
* specify a NotificationChannel ID.
*/
@Deprecated
public Builder(@NonNull Context context) {
this(context, (String) null);
}
val builder: NotificationCompat.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder(this@MainActivity, CHANNEL_ID)
} else {
NotificationCompat.Builder(this@MainActivity)
}
참고
https://developer.android.com/guide/topics/ui/notifiers/notifications?hl=ko
https://developer.android.com/training/notify-user/channels?hl=ko
https://developer.android.com/reference/android/app/NotificationChannel
'안드로이드 > 안드로이드' 카테고리의 다른 글
[Android/Kotlin] attachToParent (0) | 2023.09.05 |
---|---|
[Android/Kotlin] 프래그먼트안 프래그먼트에서 뒤로가기 (0) | 2023.09.04 |
[Android/Kotlin] 리사이클러뷰(RecyclerView) 스크롤 이벤트 (2) | 2023.08.31 |
[Android/Kotlin] 알림(Notification)아이디 채널아이디 (2) | 2023.08.30 |
[Android/Kotlin] 뷰 바인딩(ViewBinding) (2) | 2023.08.28 |