HOME > android > basic

안드로이드 - NotificationListener를 이용하여 노티 정보 받기

By JS | 10 Nov 2018

NotificationListenerService

NotificationListenerService는 Notification에 대한 정보를 받을 수 있는 객체입니다. 안드로이드 SDK는 NotificationManager에 직접 listener를 등록하는 코드는 제공하고 있지 않습니다. 정보를 받고 싶다면 NotificationListenerService를 상속받은 새로운 서비스를 구현하여야 합니다.

서비스 구현

아래처럼 NotificationListenerService를 상속받고 다음 두개의 메소드를 구현해야 합니다.

  • onNotificationPosted: 새로운 노티피케이션이 추가될 때 호출됩니다.
  • onNotificationRemoved: 노티피케이션이 제거될 때 호출됩니다.

아래 코드처럼 두개의 메소드가 호출될 때 로그가 출력되도록 하였습니다.

public class MyNotificationListener extends NotificationListenerService {
    public final static String TAG = "MyNotificationListener";

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        super.onNotificationRemoved(sbn);

        Log.d(TAG, "onNotificationRemoved ~ " +
                " packageName: " + sbn.getPackageName() +
                " id: " + sbn.getId());
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        super.onNotificationPosted(sbn);

        Notification notification = sbn.getNotification();
        Bundle extras = sbn.getNotification().extras;
        String title = extras.getString(Notification.EXTRA_TITLE);
        CharSequence text = extras.getCharSequence(Notification.EXTRA_TEXT);
        CharSequence subText = extras.getCharSequence(Notification.EXTRA_SUB_TEXT);
        Icon smallIcon = notification.getSmallIcon();
        Icon largeIcon = notification.getLargeIcon();

        Log.d(TAG, "onNotificationPosted ~ " +
                " packageName: " + sbn.getPackageName() +
                " id: " + sbn.getId() +
                " postTime: " + sbn.getPostTime() +
                " title: " + title +
                " text : " + text +
                " subText: " + subText);
    }

}

AndroidManifest 설정

AndroidManifest.xml에는 위에서 구현한 서비스를 등록해야 합니다. 안드로이드 프레임워크만 접근할 수 있도록 서비스의 퍼미션에 BIND_NOTIFICATION_LISTENER_SERVICE를 설정하고, 아래와 같은 인텐트필터를 설정해야 합니다.

<service android:name=".MyNotificationListener"
    android:label="My Notification Listener"
    android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
    <intent-filter>
        <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>
</service>

퍼미션을 설정하는 이유는... 저 퍼미션은 SystemServer(system)만 갖을 수 있습니다. 따라서 3rd party가 저 서비스를 실행할 수 없고 오직 NotificationManager에서만 접근할 수 있습니다.

인텐트필터를 설정하는 이유는 저 action으로 NotificationManager가 단말에 등록된 서비스를 찾는데 사용하기 때문입니다. 만약 인텐트필터를 저렇게 등록하지 않으면 노티를 알림받지 못합니다.

사용자로부터 권한 받기

지금까지 서비스를 구현하였고 AndroidManifest에 등록하였습니다. 마지막으로 노티피케이션에 대한 정보를 받으려면 사용자 동의를 받아야 합니다.

간혹 3rd party app들이 노티피케이션에 id와 pw를 보여주기도 합니다. 이처럼 노티피케이션은 개인정보와 관련된 부분이기 때문에 노티피케이션 정보를 받으려면 사용자로부터 권한을 부여받아야 합니다.

구현방법은... 먼저 권한이 있는지 체크하고, 권한을 받는 UI를 실행하여 사용자가 내 앱에 권한을 주도록 해야 합니다.

아래 코드는 현재 이 앱이 권한을 갖고 있는지 체크하는 코드입니다.

private boolean permissionGrantred() {
    Set<String> sets = NotificationManagerCompat.getEnabledListenerPackages(this);
    if (sets != null && sets.contains(getPackageName())) {
        return true;
    } else {
        return false;
    }
}

getEnabledListenerPackages는 내부적으로 Settings에 저장된 string을 가져옵니다. 그 string은 권한을 갖고 있는 packageName을 나열한 것이고, Set객체로 return됩니다. 우리는 리턴받은 Set에서 내 앱의 packageName이 있는지만 체크하면 됩니다.

구현한 앱 실행해보기

앱을 실행해보면 처음에는 권한이 없기 때문에 권한을 받을 수 있는 Activity가 실행됩니다.

notification-listener

UI에서 내 앱에 권한을 주면 NotificationManager는 내가 구현한 서비스를 실행하고, 노티피케이션에 대한 정보를 서비스로 전달해 줍니다.

노티피케이션이 등록되거나 삭제될 때 아래처럼 로그가 출력됩니다.

11-10 14:23:51.579 3100-3100/com.codechacha.notificationlistener D/MyNotificationListener: onNotificationRemoved ~  packageName: com.google.android.setupwizard id: 5
11-10 14:23:51.692 3100-3100/com.codechacha.notificationlistener D/MyNotificationListener: onNotificationPosted ~  packageName: android id: 40 postTime: 1541827431588 title: Android Setup is using battery text : Tap for details on battery and data usage subText: null
11-10 14:23:51.703 3100-3100/com.codechacha.notificationlistener D/MyNotificationListener: onNotificationPosted ~  packageName: com.google.android.setupwizard id: 6 postTime: 1541827431588 title: Preparing for setup… text :  subText: null

정리

예제로 NotificationListenerService를 구현한 앱을 만들어 보았습니다. 두개의 메소드만 구현해보았는데요, NotificationListenerService에는 더 많은 정보를 callback 받는 함수들이 정의되어 있습니다. 필요한 내용이 있으면 추가로 구현해서 사용하시면 됩니다.

메소드에 대한 자세한 설명은 Android developers에서 확인할 수 있습니다.

참고