9. 로컬 알림 (AppsKitSDKLocalNotificationManager)
AKS는 자체 로컬 알림을 표시하는 데 사용할 수 있는 간단한 로컬 알림 도구 모음을 제공합니다. 큐, 알림 빌더, 추상 BroadcastReceiver로 구성되어 있습니다. AKS는 자체 매니페스트에 리시버를 등록하거나 알림을 예약해 주지 않습니다. 두 작업 모두 직접 구현해야 합니다.
9.1 매니페스트
AppsKitSDKLocalNotificationBroadCastReceiver를 상속하고(§9.2 참고), 해당 서브클래스를 <receiver>로 선언하여 §2의 동일한 <application> 요소에 포함하세요.
<application
android:name=".YourApplication">
<receiver
android:name=".YourNotificationReceiver"
android:exported="false" />
</application>Android 13 이상(API 33)을 타겟팅하는 경우 알림 런타임 권한도 추가하세요. AKS 자체 매니페스트에는 이 권한이 선언되어 있지 않으므로 자동으로 병합되지 않습니다.
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />POST_NOTIFICATIONS는 런타임 권한이므로, 실제로 알림을 표시하려면 먼저 사용자에게 권한을 요청해야 합니다(예: ActivityResultContracts.RequestPermission() 사용).
9.2 큐에 알림 추가하기
AppsKitSDKLocalNotificationBroadCastReceiver를 상속하고 checkNotifications()를 구현하세요. 이 메서드는 리시버가 실행될 때마다 호출되는 훅으로, 알림을 표시할 시점인지 판단하는 데 사용합니다.
class YourNotificationReceiver : AppsKitSDKLocalNotificationBroadCastReceiver() {
override fun checkNotifications() {
addNotificationInQueue(
NotificationModel(
id = "daily_reminder", // dedup key — a second add with the same id is ignored
title = "Come back!",
description = "You have unfinished items waiting.",
icon = R.drawable.ic_notification,
notificationId = 1001, // the actual Android notification ID passed to notify()
targetScreen = "com.yourapp.MainActivity" // fully-qualified Activity class opened on tap
)
)
}
}checkNotifications()가 반환되면 onReceive가 즉시 AppsKitSDKLocalNotificationManager.showNotification(context)를 자동으로 호출합니다. 이 메서드는 큐에서 가장 먼저 추가된 NotificationModel을 꺼내 알림을 표시합니다. 이 흐름에서는 showNotification을 직접 호출할 필요 없이 checkNotifications() 안에서 큐에 알림을 추가하기만 하면 됩니다.
큐를 통해 알림을 표시하는 이 경로는 Android 13 이상에서
POST_NOTIFICATIONS권한을 자체적으로 확인합니다. 권한이 없으면 로그 한 줄만 남기고 알림 표시를 건너뛰므로, §9.1에 따라 먼저 권한을 요청하세요.
9.3 알림 예약
AKS는 이 리시버를 등록하거나 정해진 일정에 따라 실행하지 않습니다. onReceive가 실행될 시점은 직접 결정해야 하며, 일반적으로 AlarmManager를 사용합니다.
val intent = Intent(context, YourNotificationReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + intervalMs,
intervalMs,
pendingIntent
)intervalMs에는 원하는 주기를 하드코딩하거나 AKS 포털의 원격 설정에 지정된 값(HOURS_TO_MAKE_NOTIFICATION, 미설정 시 기본값 2시간)을 사용할 수 있습니다. 이 값은 리시버 기본 클래스의 getTimeIntervalInMilliSeconds()로 가져올 수 있지만, 해당 메서드는 protected이므로 위 코드의 호출 위치가 아닌 서브클래스 내부에서 호출해야 합니다.
class YourNotificationReceiver : AppsKitSDKLocalNotificationBroadCastReceiver() {
fun intervalMillis(): Long = getTimeIntervalInMilliSeconds()
override fun checkNotifications() { /* ... */ }
}
AlarmManager.setRepeating은 Doze/배터리 최적화가 적용된 상태에서는 정확한 시점에 실행되지 않습니다. 유휴 상태에서도 안정적으로 실행해야 한다면 실행될 때마다setExactAndAllowWhileIdle로 다음 알람을 다시 예약하거나,WorkManager의PeriodicWorkRequest(최소 간격 15분)로 전환하세요. AKS는 어느 쪽도 강제하지 않으므로 앱에 적합한 방식을 선택하면 됩니다. 또한 기기가 재부팅되면 알람이 유지되지 않으므로 직접 다시 등록해야 합니다(예:BOOT_COMPLETED리시버에서 등록).
9.4 알림 직접 표시하기(큐 미사용)
위의 큐/리시버 흐름을 거치지 않고 즉시 알림을 표시하려면 다음과 같이 호출하세요.
// Tapping opens the Activity at classPath
AppsKitSDKLocalNotificationManager.showNotification(
context = this,
id = 2001,
classPath = "com.yourapp.MainActivity",
channelId = "general",
title = "New message",
message = "You've got a new message waiting.",
notificationIcon = R.drawable.ic_notification
)
// Or pass a fully-built Intent instead of a class path
AppsKitSDKLocalNotificationManager.showNotification(
context = this,
id = 2002,
intent = Intent(this, MainActivity::class.java).putExtra("from", "notification"),
channelId = "general",
title = "New message",
message = "Tap to view details.",
notificationIcon = R.drawable.ic_notification
)두 오버로드 모두 알림 채널이 아직 없으면 자동으로 생성합니다. §9.2의 큐 기반 경로와 달리 두 오버로드 모두 POST_NOTIFICATIONS 권한을 자체적으로 확인하지 않습니다. Android 13 이상에서는 런타임 권한을 직접 요청해야 하며, 그렇지 않으면 호출해도 별다른 오류 없이 알림이 표시되지 않을 수 있습니다.