Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.notimanager"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>

<application
android:name=".NotiManager"
Expand All @@ -12,13 +15,13 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.NotiManger"
android:theme="@style/Theme.NotiManager"
android:enableOnBackInvokedCallback="true"
tools:targetApi="35">
<activity
android:name=".presentation.ui.activity.MainActivity"
android:exported="true"
android:theme="@style/Theme.NotiManger">
android:theme="@style/Theme.NotiManager">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand All @@ -34,7 +37,11 @@
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>


<service
android:name=".domain.service.ForegroundNotiService"
android:foregroundServiceType="dataSync" />

</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -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)

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
@@ -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()
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
}
}
Expand All @@ -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) }

Expand Down Expand Up @@ -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)
}
}
}

Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -14,23 +19,41 @@ 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 ->
if (!isGranted) {
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")

}
}
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<resources>
<string name="app_name">NotiManger</string>
<string name="app_name">NotiManager</string>
</resources>
2 changes: 1 addition & 1 deletion app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>

<style name="Theme.NotiManger" parent="android:Theme.Material.Light.NoActionBar" />
<style name="Theme.NotiManager" parent="android:Theme.Material.Light.NoActionBar" />
</resources>
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ dependencyResolutionManagement {
}
}

rootProject.name = "NotiManger"
rootProject.name = "NotiManager"
include(":app")
Loading