seong
Flutter + Kotlin - 다른 앱의 알림 받기 ( NotificationListenerService ) 본문
Flutter로 앱을 개발 중 Ble기기에 AOS로 오는 앱의 알림을 전달 해주는 기능이 필요해졌다.
AOS 기기에서 나의 앱에서 다른 앱들의 알림 읽어오는 방법
받는 방식은 간단하게 아래 처럼 진행된다.
NotificationListenerService 객체 및 Listener 생성 -> Listener로 MainActivity에 전달 -> Flutter에 전달
1. 권한 추가
<service
android:name=".CustomNotificationService"
android:exported="false"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
2. MainActivity
알림을 받기 위해 권한을 확인 및 받는 부분, 데이터를 MainActivity에서 Listen하는 부분이 있다.
class MainActivity : FlutterActivity(),AppNotificationListener{
lateinit var methodChannel: MethodChannel
private val customService = CustomNotificationService()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//OS의 notification을 가져오기 위한 권한 선언
if(!isNotificationPermissionGranted()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS))
}
}
//Listener 등록
customService.addNotificationListener(this)
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "android")
methodChannel.setMethodCallHandler { call, result ->
when (call.method) {
// .. 메서드 채널 통신
}
}
}
/**
* Notification 권한 체크
*/
private fun isNotificationPermissionGranted(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
return notificationManager.isNotificationListenerAccessGranted(
ComponentName(
application,
CustomNotificationService::class.java
)
)
} else {
return NotificationManagerCompat.getEnabledListenerPackages(applicationContext)
.contains(applicationContext.packageName)
}
}
// Service에서 notification이 되면 함수 실행
override fun readNotification(notification: NotificationModel) {
// NotificationModel로 메서드 채널에 전달 할 수 없어서 toMap 해줌.
val notificationMap = mapOf(
"packageName" to notification.packageName,
"title" to notification.title,
"text" to notification.text
)
methodChannel.invokeMethod("notification", notificationMap)
}
}
3. Listener
interface AppNotificationListener {
fun readNotification(notification: NotificationModel)
}
4. CustomNotificationService 작성
싱글톤으로 listener를 생성했고, 알림 데이터가 생성 될 때 마다 listener를 통해서 알려주었다.
모든 알림에 대해 전달해줄 필요가 없어 내가 원하는 packageName만 필터링도 작성했다.
import android.app.Notification
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
class CustomNotificationService :NotificationListenerService(){
companion object {
val listeners = ArrayList<AppNotificationListener>()
}
// MainActivity에서 listen할 수 있도록 listener 선언
fun addNotificationListener(listener: AppNotificationListener){
listeners.add(listener)
}
// 최초 Service가 연결 되었을때 호출
override fun onListenerConnected( ) {
super.onListenerConnected()
}
// Service가 닫혔을 경우 호출
override fun onListenerDisconnected() {
super.onListenerDisconnected()
}
// OS에 Notification이 생겼을 경우 호출
override fun onNotificationPosted(sbn: StatusBarNotification?) {
super.onNotificationPosted(sbn)
val extras = sbn?.notification?.extras
// 변수
val extraTitle = extras?.getString(Notification.EXTRA_TITLE)
val extraText = extras?.getString(Notification.EXTRA_TEXT)
val extraApp = sbn?.packageName
// 내가 필요한 패키지 명들만 필터링
if(!filterByPackageName(extraApp.toString())){
Log.d("Notification","Filtered : $extraApp")
return
}
// 필터링 한 데이터를 MainActivity에 전달
val notificationModel = NotificationModel(extraApp.toString(),extraTitle.toString(),extraText.toString())
for(listener in listeners){
listener.readNotification(notificationModel)
}
}
// PackageName Filter함수
private fun filterByPackageName(packageName: String): Boolean {
return PackageNameEnum.entries.any { packageEnum ->
packageName.contains(packageEnum.packageName, ignoreCase = true)
}
}
}
'Kotlin' 카테고리의 다른 글
AOS - Minimum supported Gradle version is 8.7. Current version is 8.5. (0) | 2024.07.10 |
---|