diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6f088d8..83e1df2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,7 +1,10 @@
+
+
+ android:theme="@style/Theme.NotiManager">
@@ -34,7 +37,11 @@
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt b/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt
index 01e37b0..b51cae2 100644
--- a/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt
+++ b/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt
@@ -31,4 +31,9 @@ class NotificationRepository(
override suspend fun insertAppIcon(appIconModel: AppIconModel): Long {
return appIconDao.insert(appIconModel)
}
+
+ override suspend fun getPriorityNotificationCount(appName: String): Int{
+ return notificationDao.getPriorityNotificationCount(appName)
+
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/notimanager/data/source/local/dao/NotificationDao.kt b/app/src/main/java/com/example/notimanager/data/source/local/dao/NotificationDao.kt
index 26cceb6..d2a4203 100644
--- a/app/src/main/java/com/example/notimanager/data/source/local/dao/NotificationDao.kt
+++ b/app/src/main/java/com/example/notimanager/data/source/local/dao/NotificationDao.kt
@@ -132,4 +132,12 @@ interface NotificationDao {
@Query("UPDATE Notification SET isRead = 1 WHERE appName = :appName AND subText = :subText")
suspend fun updateSubTextAsRead(appName: String, subText: String): Int
+
+ @Query("""
+ SELECT COUNT(*)
+ FROM Notification AS n
+ INNER JOIN app_icon AS ai ON n.appName = ai.notiAppName AND ai.priorityActive = 1
+ WHERE n.appName = :appName AND n.isRead = 0
+ """)
+ suspend fun getPriorityNotificationCount(appName: String): Int
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt b/app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt
index 93133bb..6756966 100644
--- a/app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt
+++ b/app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt
@@ -10,4 +10,5 @@ interface NotificationRepositoryInterface {
suspend fun insertNotificationMeta(metaModel: NotificationMetaModel): Long
suspend fun insertNotificationIcon(notificationIconModel: NotificationIconModel): Long
suspend fun insertAppIcon(appIconModel: AppIconModel): Long
+ suspend fun getPriorityNotificationCount(appName: String): Int
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/notimanager/domain/service/ForegroundNotiService.kt b/app/src/main/java/com/example/notimanager/domain/service/ForegroundNotiService.kt
new file mode 100644
index 0000000..14b52ce
--- /dev/null
+++ b/app/src/main/java/com/example/notimanager/domain/service/ForegroundNotiService.kt
@@ -0,0 +1,96 @@
+package com.example.notimanager.domain.service
+
+import android.Manifest
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.app.Service
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.IBinder
+import androidx.core.app.ActivityCompat
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import com.example.notimanager.R
+import com.example.notimanager.presentation.ui.activity.MainActivity
+
+class ForegroundNotiService: Service() {
+ private val channelId = "NotiManagerChannel"
+ private val groupId = "NotiManagerGroup"
+
+ override fun onCreate() {
+ super.onCreate()
+ createNotificationChannel()
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ val clearGroup = intent?.extras?.getBoolean("clearGroup") ?: false
+ if (clearGroup) clearGroupNotifications()
+
+ val appName = intent?.extras?.getString("appName") ?: ""
+ val content = intent?.extras?.getString("content") ?: ""
+ val isGroupSummary = intent?.extras?.getBoolean("isGroupSummary") ?: false
+ putNotification(appName, content, isGroupSummary)
+
+ return START_STICKY
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ stopForeground(STOP_FOREGROUND_REMOVE)
+ }
+
+ private fun putNotification(
+ appName: String,
+ content: String,
+ isGroupSummary: Boolean) {
+ val notificationIntent = Intent(this, MainActivity::class.java).apply {
+ putExtra("appName", appName)
+ }
+ val pendingIntent = PendingIntent
+ .getActivity(this,
+ 0,
+ notificationIntent,
+ PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
+
+ val notification = NotificationCompat.Builder(this, channelId)
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentTitle(appName)
+ .setContentText(content)
+ .setContentIntent(pendingIntent)
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .setGroup(groupId)
+ .setAutoCancel(true)
+ .setOngoing(true)
+ .setGroupSummary(isGroupSummary)
+ .build()
+
+ if (ActivityCompat.checkSelfPermission(
+ this,
+ Manifest.permission.POST_NOTIFICATIONS
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ return
+ }
+
+ NotificationManagerCompat.from(this).notify(appName.hashCode(), notification)
+ }
+
+ private fun createNotificationChannel() {
+ val channel = NotificationChannel(
+ channelId,
+ "NotiManager Channel",
+ NotificationManager.IMPORTANCE_DEFAULT
+ )
+ val manager = getSystemService(NotificationManager::class.java)
+ manager.createNotificationChannel(channel)
+ }
+
+ private fun clearGroupNotifications() {
+ NotificationManagerCompat.from(this).cancelAll()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt b/app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt
index 5010f69..2f04411 100644
--- a/app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt
+++ b/app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt
@@ -1,5 +1,6 @@
package com.example.notimanager.domain.service
+import android.content.Intent
import android.graphics.drawable.Icon
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
@@ -34,7 +35,7 @@ class NotiListenerService: NotificationListenerService() {
val notification = sbn.notification
val appName = NameGetter.getAppName(this, sbn)
- val title = notification.extras.getString("android.title") ?: ""
+ val title = notification.extras.getCharSequence("android.title")?.toString() ?: ""
val subText = notification.extras.getString("android.subText") ?: ""
val content = notification.extras.getCharSequence("android.text")?.toString() ?: ""
val postTime = sbn.postTime
@@ -50,6 +51,7 @@ class NotiListenerService: NotificationListenerService() {
insertNotificationMeta(id, sbn.packageName)
insertNotificationIcon(id, notification.getLargeIcon(), notification.smallIcon, notification.color)
insertAppIcon(appName, sbn.packageName)
+ putNotification(appName)
}
}
}
@@ -75,6 +77,7 @@ class NotiListenerService: NotificationListenerService() {
id: Long,
notificationPackage: String?,
){
+ // TODO: 원래 pendingIntent의 extras 추출해서 넣어보기
val intent = packageManager.getLaunchIntentForPackage(notificationPackage ?: "")
val intentArray = intent?.let { IntentHelper.saveIntent(it) }
@@ -118,5 +121,16 @@ class NotiListenerService: NotificationListenerService() {
)
notificationRepository.insertAppIcon(appIconModel)
}
+
+ private suspend fun putNotification(appName: String){
+ val count = notificationRepository.getPriorityNotificationCount(appName)
+ if (count != 0){
+ val serviceIntent = Intent(this, ForegroundNotiService::class.java).apply {
+ putExtra("appName", appName)
+ putExtra("content", count.toString())
+ }
+ startService(serviceIntent)
+ }
+ }
}
diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/activity/MainActivity.kt b/app/src/main/java/com/example/notimanager/presentation/ui/activity/MainActivity.kt
index 55243fd..9dd14d4 100644
--- a/app/src/main/java/com/example/notimanager/presentation/ui/activity/MainActivity.kt
+++ b/app/src/main/java/com/example/notimanager/presentation/ui/activity/MainActivity.kt
@@ -1,10 +1,15 @@
package com.example.notimanager.presentation.ui.activity
+import android.content.Intent
import android.os.Bundle
+import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
+import androidx.navigation.NavController
+import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
+import com.example.notimanager.domain.service.ForegroundNotiService
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationPermissionViewModel
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationServicePermissionViewModel
import com.example.notimanager.presentation.ui.navigation.AppNavHost
@@ -14,12 +19,16 @@ import dagger.hilt.android.AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val serviceViewModel: NotificationServicePermissionViewModel by viewModels()
private val notificationViewModel: NotificationPermissionViewModel by viewModels()
+ private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ val appName = intent.extras?.getString("appName") ?: ""
setContent {
- AppNavHost(navController = rememberNavController())
+ navController = rememberNavController()
+ AppNavHost(navController = navController as NavHostController)
+ if (appName != "" && appName != "NotiManager") navController.navigate("titleScreen/$appName")
}
notificationViewModel.isNotificationPermissionGranted.observe(this) { isGranted ->
@@ -27,10 +36,24 @@ class MainActivity : ComponentActivity() {
notificationViewModel.requestPermission(this)
}
}
+ val serviceIntent = Intent(this, ForegroundNotiService::class.java).apply {
+ putExtra("clearGroup", true)
+ putExtra("appName", "NotiManager")
+ putExtra("content", "실행 중입니다.")
+ putExtra("isGroupSummary", true)
+ }
+ startService(serviceIntent)
}
override fun onResume() {
super.onResume()
serviceViewModel.checkNotificationServicePermission()
}
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ val appName = intent.extras?.getString("appName") ?: ""
+ if (appName != "" && appName != "NotiManager") navController.navigate("titleScreen/$appName")
+
+ }
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e89c2ae..15b4d85 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,3 @@
- NotiManger
+ NotiManager
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 98fbe13..4d04581 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 6371a51..c1fdb14 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -19,5 +19,5 @@ dependencyResolutionManagement {
}
}
-rootProject.name = "NotiManger"
+rootProject.name = "NotiManager"
include(":app")