Android

Notification을 수신해보자!

KimDaQ 2022. 12. 8. 14:59

이번 사이드 프로젝트로 잠금화면 앱을 만들어보면서, 알림을 잠금화면에 띄우는 기능을 만들어야했습니다. 

안드로이드에서는 어떻게 알림을 가져올 수 있을까요?

 

NotificationListenerService

다행히 알림이 왔을때 시스템에서 호출받을 수 있는 서비스클래스가 존재합니다. 바로 NotificationListenerService입니다.

NotificationListenerService는 Service를 상속하고 있어서 사용을 위해서 Mainfest.xml에 등록해주는 과정이 필요합니다.

<service
	android:name="com.knocklock.presentation.lockscreen.LockScreenNotificationListener"
	android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
	android:exported="true">
	<intent-filter>
		<action android:name="android.service.notification.NotificationListenerService" />
	</intent-filter>
 </service>

위와 같이 Mainfest.xml에서 service를 등록하고 intent-filter에 NotificationListenerService를 포함합니다. 

또한 BIND_NOTIFICATION_LISTENER_SERVICE 권한을 부여해주는데, 이 권한은 앱에서 임의로 권한을 획득할 수 없고, 사용자가 설정에서 부여해줘야합니다. 

따라서 다음과 같은 코드가 필요합니다.

// MainActivity
private fun permissionGranted() : Boolean{
	val sets: Set<String> = NotificationManagerCompat.getEnabledListenerPackages(this)
    return sets.contains(packageName)
}

NotificationManagerCompat.getEnabledListenerPackages(context: Context)는 알림 접근이 허용된 목록을 불러옵니다.

목록에는 알림 접근이 허용된 패키지들의 이름이 들어가고 있는데, 현재 실행하고 있는 앱이 존재하지 않는다면,false를 반환하여 권한을 설정할 수 있도록 설정 창으로 이동해줍니다. 

if(!permissionGranted()){
	val intent = Intent(
    	"android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"
    )
    startActivity(intent)
}

 

알림 접근 허용에서 허용 안된 현재 애플리케이션의 권한을 허용으로 바꿔주면서 이제 알림을 수신할 수 있습니다. 

 

NotificationListenerService 구현

지금까지 사전작업이였다면 이제 Notification에서 내용물을 가져와 보겠습니다. 

class LockScreenNotificationListener : NotificaionListenerService(){
	override fun onNotificationPosted(sbn : StatusBarNotification?){
    	super.onNotificationPosted(sbn)
    }
    override fun onNotificationRemoved(sbn : StatusBarNotification?){
    	super.onNotificationPosted(sbn)
    }
}

NotificationListenerService 클래스는 위의 두가지 메소드를 필수로 구현해야합니다.

각각 알림이 생성될때, 제거될 때 호출됩니다. 

override fun onNotificationPosted(sbn: StatusBarNotification?) {
        super.onNotificationPosted(sbn)

        val packageName = sbn?.packageName
        if (sbn != null && !TextUtils.isEmpty(packageName)) {
            val notification: Notification = sbn.notification
            val extras = notification.extras
            val title = extras.getString(Notification.EXTRA_TITLE)
            val text = extras.getString(Notification.EXTRA_TEXT)
            val subText = extras.getString(Notification.EXTRA_SUB_TEXT)
            val smallIcon = notification.smallIcon
            val largeIcon = notification.getLargeIcon()
            

        }
}

StatusBarNotification에서 notification을 얻을 수 있습니다.

notification의 extras에서는 알림의 제목, 텍스트, 서브 텍스트, 아이콘등을 얻을 수 있습니다.

또한 조건문에 필터를 추가해서 특정한 앱의 notification만을 수신할 수도 있습니다.

카카오톡 메세지

실제로 카카오톡 메시지가 오면 위의 그림과 같습니다. subText는 그룹 채팅방일 때 , 그룹채팅방이름으로 설정이 됩니다.

Tip!

저는 알림을 수신을 테스트하기 위해서, 알림이 가장 많이 올 수 있는 대화가 많은 오픈 채팅방에 들어가서 알림을 수신하고는 했었습니다. 하지만 터미널을 통해서 Notification을 생성할 수 있는 방법이 있습니다!

adb shell cmd notification post -S bigtext -t 'Title' 'Tag' 'Multiline text'

adb 명령어를 이용해서, Title과 내용(Multiline text)를 지정해서 Notification을 생성하면, 위에서 생성한 Listener를 통해서 내용을 가져올 수 있습니다.

이 방법을 통해서, 알림을 생성하고 디버깅을 할 수 있습니다.

 

Notification을 수신하면, 내부 RoomDatabase에 저장하고, 이를 관찰하여 View에 띄우는 동작입니다. 이렇게 알림 수신 테스트를 쉽게 할 수 있습니다. 

 

마무리

지금까지 알림을 수신하는 방법을 알아보았는데요. 이미 구현된 클래스가 존재하여서 쉽게 구현을 해볼 수 있었습니다. 알림 수신을 완료헀으니.. 이제 잠금화면을 구현하는데 힘을 쏟아야할꺼 같습니다.!