Skip to content

Commit 039ca76

Browse files
authored
Merge pull request #45 from Richter3766/Feat/issue-#39
Feat/issue #39 - 상태바 표시
2 parents 03168ec + 556f5d7 commit 039ca76

File tree

10 files changed

+162
-8
lines changed

10 files changed

+162
-8
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.example.notimanager"
34
xmlns:tools="http://schemas.android.com/tools">
45
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
6+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
7+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
58

69
<application
710
android:name=".NotiManager"
@@ -12,13 +15,13 @@
1215
android:label="@string/app_name"
1316
android:roundIcon="@mipmap/ic_launcher_round"
1417
android:supportsRtl="true"
15-
android:theme="@style/Theme.NotiManger"
18+
android:theme="@style/Theme.NotiManager"
1619
android:enableOnBackInvokedCallback="true"
1720
tools:targetApi="35">
1821
<activity
1922
android:name=".presentation.ui.activity.MainActivity"
2023
android:exported="true"
21-
android:theme="@style/Theme.NotiManger">
24+
android:theme="@style/Theme.NotiManager">
2225
<intent-filter>
2326
<action android:name="android.intent.action.MAIN" />
2427

@@ -34,7 +37,11 @@
3437
<action android:name="android.service.notification.NotificationListenerService" />
3538
</intent-filter>
3639
</service>
37-
40+
41+
<service
42+
android:name=".domain.service.ForegroundNotiService"
43+
android:foregroundServiceType="dataSync" />
44+
3845
</application>
3946

4047
</manifest>

app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ class NotificationRepository(
3131
override suspend fun insertAppIcon(appIconModel: AppIconModel): Long {
3232
return appIconDao.insert(appIconModel)
3333
}
34+
35+
override suspend fun getPriorityNotificationCount(appName: String): Int{
36+
return notificationDao.getPriorityNotificationCount(appName)
37+
38+
}
3439
}

app/src/main/java/com/example/notimanager/data/source/local/dao/NotificationDao.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,12 @@ interface NotificationDao {
132132

133133
@Query("UPDATE Notification SET isRead = 1 WHERE appName = :appName AND subText = :subText")
134134
suspend fun updateSubTextAsRead(appName: String, subText: String): Int
135+
136+
@Query("""
137+
SELECT COUNT(*)
138+
FROM Notification AS n
139+
INNER JOIN app_icon AS ai ON n.appName = ai.notiAppName AND ai.priorityActive = 1
140+
WHERE n.appName = :appName AND n.isRead = 0
141+
""")
142+
suspend fun getPriorityNotificationCount(appName: String): Int
135143
}

app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ interface NotificationRepositoryInterface {
1010
suspend fun insertNotificationMeta(metaModel: NotificationMetaModel): Long
1111
suspend fun insertNotificationIcon(notificationIconModel: NotificationIconModel): Long
1212
suspend fun insertAppIcon(appIconModel: AppIconModel): Long
13+
suspend fun getPriorityNotificationCount(appName: String): Int
1314
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.example.notimanager.domain.service
2+
3+
import android.Manifest
4+
import android.app.NotificationChannel
5+
import android.app.NotificationManager
6+
import android.app.PendingIntent
7+
import android.app.Service
8+
import android.content.Intent
9+
import android.content.pm.PackageManager
10+
import android.os.IBinder
11+
import androidx.core.app.ActivityCompat
12+
import androidx.core.app.NotificationCompat
13+
import androidx.core.app.NotificationManagerCompat
14+
import com.example.notimanager.R
15+
import com.example.notimanager.presentation.ui.activity.MainActivity
16+
17+
class ForegroundNotiService: Service() {
18+
private val channelId = "NotiManagerChannel"
19+
private val groupId = "NotiManagerGroup"
20+
21+
override fun onCreate() {
22+
super.onCreate()
23+
createNotificationChannel()
24+
}
25+
26+
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
27+
val clearGroup = intent?.extras?.getBoolean("clearGroup") ?: false
28+
if (clearGroup) clearGroupNotifications()
29+
30+
val appName = intent?.extras?.getString("appName") ?: ""
31+
val content = intent?.extras?.getString("content") ?: ""
32+
val isGroupSummary = intent?.extras?.getBoolean("isGroupSummary") ?: false
33+
putNotification(appName, content, isGroupSummary)
34+
35+
return START_STICKY
36+
}
37+
38+
override fun onBind(intent: Intent?): IBinder? {
39+
return null
40+
}
41+
42+
override fun onDestroy() {
43+
super.onDestroy()
44+
stopForeground(STOP_FOREGROUND_REMOVE)
45+
}
46+
47+
private fun putNotification(
48+
appName: String,
49+
content: String,
50+
isGroupSummary: Boolean) {
51+
val notificationIntent = Intent(this, MainActivity::class.java).apply {
52+
putExtra("appName", appName)
53+
}
54+
val pendingIntent = PendingIntent
55+
.getActivity(this,
56+
0,
57+
notificationIntent,
58+
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
59+
60+
val notification = NotificationCompat.Builder(this, channelId)
61+
.setSmallIcon(R.mipmap.ic_launcher)
62+
.setContentTitle(appName)
63+
.setContentText(content)
64+
.setContentIntent(pendingIntent)
65+
.setPriority(NotificationCompat.PRIORITY_HIGH)
66+
.setGroup(groupId)
67+
.setAutoCancel(true)
68+
.setOngoing(true)
69+
.setGroupSummary(isGroupSummary)
70+
.build()
71+
72+
if (ActivityCompat.checkSelfPermission(
73+
this,
74+
Manifest.permission.POST_NOTIFICATIONS
75+
) != PackageManager.PERMISSION_GRANTED
76+
) {
77+
return
78+
}
79+
80+
NotificationManagerCompat.from(this).notify(appName.hashCode(), notification)
81+
}
82+
83+
private fun createNotificationChannel() {
84+
val channel = NotificationChannel(
85+
channelId,
86+
"NotiManager Channel",
87+
NotificationManager.IMPORTANCE_DEFAULT
88+
)
89+
val manager = getSystemService(NotificationManager::class.java)
90+
manager.createNotificationChannel(channel)
91+
}
92+
93+
private fun clearGroupNotifications() {
94+
NotificationManagerCompat.from(this).cancelAll()
95+
}
96+
}

app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.example.notimanager.domain.service
22

3+
import android.content.Intent
34
import android.graphics.drawable.Icon
45
import android.service.notification.NotificationListenerService
56
import android.service.notification.StatusBarNotification
@@ -34,7 +35,7 @@ class NotiListenerService: NotificationListenerService() {
3435
val notification = sbn.notification
3536

3637
val appName = NameGetter.getAppName(this, sbn)
37-
val title = notification.extras.getString("android.title") ?: ""
38+
val title = notification.extras.getCharSequence("android.title")?.toString() ?: ""
3839
val subText = notification.extras.getString("android.subText") ?: ""
3940
val content = notification.extras.getCharSequence("android.text")?.toString() ?: ""
4041
val postTime = sbn.postTime
@@ -50,6 +51,7 @@ class NotiListenerService: NotificationListenerService() {
5051
insertNotificationMeta(id, sbn.packageName)
5152
insertNotificationIcon(id, notification.getLargeIcon(), notification.smallIcon, notification.color)
5253
insertAppIcon(appName, sbn.packageName)
54+
putNotification(appName)
5355
}
5456
}
5557
}
@@ -75,6 +77,7 @@ class NotiListenerService: NotificationListenerService() {
7577
id: Long,
7678
notificationPackage: String?,
7779
){
80+
// TODO: 원래 pendingIntent의 extras 추출해서 넣어보기
7881
val intent = packageManager.getLaunchIntentForPackage(notificationPackage ?: "")
7982
val intentArray = intent?.let { IntentHelper.saveIntent(it) }
8083

@@ -118,5 +121,16 @@ class NotiListenerService: NotificationListenerService() {
118121
)
119122
notificationRepository.insertAppIcon(appIconModel)
120123
}
124+
125+
private suspend fun putNotification(appName: String){
126+
val count = notificationRepository.getPriorityNotificationCount(appName)
127+
if (count != 0){
128+
val serviceIntent = Intent(this, ForegroundNotiService::class.java).apply {
129+
putExtra("appName", appName)
130+
putExtra("content", count.toString())
131+
}
132+
startService(serviceIntent)
133+
}
134+
}
121135
}
122136

app/src/main/java/com/example/notimanager/presentation/ui/activity/MainActivity.kt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package com.example.notimanager.presentation.ui.activity
22

3+
import android.content.Intent
34
import android.os.Bundle
5+
import android.util.Log
46
import androidx.activity.ComponentActivity
57
import androidx.activity.compose.setContent
68
import androidx.activity.viewModels
9+
import androidx.navigation.NavController
10+
import androidx.navigation.NavHostController
711
import androidx.navigation.compose.rememberNavController
12+
import com.example.notimanager.domain.service.ForegroundNotiService
813
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationPermissionViewModel
914
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationServicePermissionViewModel
1015
import com.example.notimanager.presentation.ui.navigation.AppNavHost
@@ -14,23 +19,41 @@ import dagger.hilt.android.AndroidEntryPoint
1419
class MainActivity : ComponentActivity() {
1520
private val serviceViewModel: NotificationServicePermissionViewModel by viewModels()
1621
private val notificationViewModel: NotificationPermissionViewModel by viewModels()
22+
private lateinit var navController: NavController
1723

1824
override fun onCreate(savedInstanceState: Bundle?) {
1925
super.onCreate(savedInstanceState)
2026

27+
val appName = intent.extras?.getString("appName") ?: ""
2128
setContent {
22-
AppNavHost(navController = rememberNavController())
29+
navController = rememberNavController()
30+
AppNavHost(navController = navController as NavHostController)
31+
if (appName != "" && appName != "NotiManager") navController.navigate("titleScreen/$appName")
2332
}
2433

2534
notificationViewModel.isNotificationPermissionGranted.observe(this) { isGranted ->
2635
if (!isGranted) {
2736
notificationViewModel.requestPermission(this)
2837
}
2938
}
39+
val serviceIntent = Intent(this, ForegroundNotiService::class.java).apply {
40+
putExtra("clearGroup", true)
41+
putExtra("appName", "NotiManager")
42+
putExtra("content", "실행 중입니다.")
43+
putExtra("isGroupSummary", true)
44+
}
45+
startService(serviceIntent)
3046
}
3147

3248
override fun onResume() {
3349
super.onResume()
3450
serviceViewModel.checkNotificationServicePermission()
3551
}
52+
53+
override fun onNewIntent(intent: Intent) {
54+
super.onNewIntent(intent)
55+
val appName = intent.extras?.getString("appName") ?: ""
56+
if (appName != "" && appName != "NotiManager") navController.navigate("titleScreen/$appName")
57+
58+
}
3659
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
<resources>
2-
<string name="app_name">NotiManger</string>
2+
<string name="app_name">NotiManager</string>
33
</resources>

app/src/main/res/values/themes.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources>
33

4-
<style name="Theme.NotiManger" parent="android:Theme.Material.Light.NoActionBar" />
4+
<style name="Theme.NotiManager" parent="android:Theme.Material.Light.NoActionBar" />
55
</resources>

settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ dependencyResolutionManagement {
1919
}
2020
}
2121

22-
rootProject.name = "NotiManger"
22+
rootProject.name = "NotiManager"
2323
include(":app")

0 commit comments

Comments
 (0)