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
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<application
android:name=".NotiManager"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.example.notimanager.data.repository

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.provider.Settings
import com.example.notimanager.domain.repository.NotificationPermissionRepositoryInterface
import javax.inject.Inject
Expand All @@ -15,9 +18,17 @@ class NotificationPermissionRepository @Inject constructor(
return flat != null && flat.contains(pkgName)
}

override fun requestPermission() {
override fun requestNotificationListenerPermission() {
val intent = Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
appContext.startActivity(intent)
}

override fun isNotificationPermissionGranted(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
appContext.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
} else {
true
}
}
}
6 changes: 3 additions & 3 deletions app/src/main/java/com/example/notimanager/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.example.notimanager.di

import com.example.notimanager.domain.usecase.NotificationPermissionUseCase
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationPermissionViewModel
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationServicePermissionViewModel
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -15,7 +15,7 @@ class AppModule {
@Singleton
fun provideNotificationPermissionViewModel(
notificationPermissionUseCase: NotificationPermissionUseCase
): NotificationPermissionViewModel {
return NotificationPermissionViewModel(notificationPermissionUseCase)
): NotificationServicePermissionViewModel {
return NotificationServicePermissionViewModel(notificationPermissionUseCase)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ package com.example.notimanager.domain.repository

interface NotificationPermissionRepositoryInterface {
fun isNotificationServiceEnabled(): Boolean
fun requestPermission()
fun requestNotificationListenerPermission()
fun isNotificationPermissionGranted(): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ class NotiListenerService: NotificationListenerService() {
val appName = NameGetter.getAppName(this, sbn)
val title = notification.extras.getString("android.title") ?: ""
val subText = notification.extras.getString("android.subText") ?: ""
val content = notification.extras.getCharSequence("android.text").toString() ?: ""
val content = notification.extras.getCharSequence("android.text")?.toString() ?: ""
val postTime = sbn.postTime

CoroutineScope(Dispatchers.IO).launch {
if (title == "" && content == "" && subText == "") return@launch
if (title == "" && content == "") return@launch

val filteredList = filterRepository.getSpecificFilteredList(appName, title, subText)
if (filteredList.isNotEmpty()) return@launch
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.example.notimanager.domain.usecase

import android.Manifest
import android.app.Activity
import android.os.Build
import com.example.notimanager.domain.repository.NotificationPermissionRepositoryInterface

class NotificationPermissionUseCase(
Expand All @@ -11,7 +14,26 @@ class NotificationPermissionUseCase(

fun requestPermission() {
if (!repository.isNotificationServiceEnabled()) {
repository.requestPermission()
repository.requestNotificationListenerPermission()
}
}

fun isNotificationPermissionGranted(): Boolean{
return repository.isNotificationPermissionGranted()
}

fun requestPermission(activity: Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
activity.requestPermissions(
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
NOTIFICATION_PERMISSION_REQUEST_CODE
)
} else {
// Android 12 이하에서는 별도 권한이 필요하지 않음
}
}

companion object {
private const val NOTIFICATION_PERMISSION_REQUEST_CODE = 1
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.notimanager.presentation.stateholder.viewmodel

import android.app.Activity
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
Expand All @@ -12,19 +13,18 @@ class NotificationPermissionViewModel @Inject constructor(
private val notificationPermissionUseCase: NotificationPermissionUseCase
) : ViewModel() {

private val _isPermissionGranted = MutableLiveData<Boolean>()
val isPermissionGranted: LiveData<Boolean> get() = _isPermissionGranted
private val _isNotificationPermissionGranted = MutableLiveData<Boolean>()
val isNotificationPermissionGranted: LiveData<Boolean> get() = _isNotificationPermissionGranted

init {
checkNotificationPermission()
}

fun checkNotificationPermission() {
_isPermissionGranted.value = notificationPermissionUseCase.isNotificationServiceEnabled()
_isNotificationPermissionGranted.value = notificationPermissionUseCase.isNotificationPermissionGranted()
}

fun requestPermission() {
notificationPermissionUseCase.requestPermission()
checkNotificationPermission()
fun requestPermission(activity: Activity) {
notificationPermissionUseCase.requestPermission(activity)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.notimanager.presentation.stateholder.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.notimanager.domain.usecase.NotificationPermissionUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class NotificationServicePermissionViewModel @Inject constructor(
private val notificationPermissionUseCase: NotificationPermissionUseCase
) : ViewModel() {

private val _isNotificationServiceEnabled = MutableLiveData<Boolean>()
val isNotificationServiceEnabled: LiveData<Boolean> get() = _isNotificationServiceEnabled

init {
checkNotificationServicePermission()
}

fun checkNotificationServicePermission() {
_isNotificationServiceEnabled.value = notificationPermissionUseCase.isNotificationServiceEnabled()
}

fun requestServicePermission() {
notificationPermissionUseCase.requestPermission()
checkNotificationServicePermission()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,31 @@ import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.navigation.compose.rememberNavController
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationPermissionViewModel
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationServicePermissionViewModel
import com.example.notimanager.presentation.ui.navigation.AppNavHost
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

private val viewModel: NotificationPermissionViewModel by viewModels()
private val serviceViewModel: NotificationServicePermissionViewModel by viewModels()
private val notificationViewModel: NotificationPermissionViewModel by viewModels()

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

setContent {
AppNavHost(navController = rememberNavController())
}

notificationViewModel.isNotificationPermissionGranted.observe(this) { isGranted ->
if (!isGranted) {
notificationViewModel.requestPermission(this)
}
}
}

override fun onResume() {
super.onResume()
viewModel.checkNotificationPermission()
serviceViewModel.checkNotificationServicePermission()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.hilt.navigation.compose.hiltViewModel
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationPermissionViewModel
import com.example.notimanager.presentation.stateholder.viewmodel.NotificationServicePermissionViewModel

@Composable
fun PermissionCheck(viewModel: NotificationPermissionViewModel = hiltViewModel()){
val isPermissionGranted by viewModel.isPermissionGranted.observeAsState()
fun PermissionCheck(viewModel: NotificationServicePermissionViewModel = hiltViewModel()){
val isPermissionGranted by viewModel.isNotificationServiceEnabled.observeAsState()

if (isPermissionGranted == false) {
SimplePermissionDialog(
title = "알림 권한 필요",
message = "알림을 받기 위해 알림 권한이 필요합니다.",
onAllow = { viewModel.requestPermission() },
onAllow = { viewModel.requestServicePermission() },
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class NotificationPermissionRepositoryTest : BehaviorSpec({
val intentSlot = slot<Intent>()

When("requestPermission 호출") {
repository.requestPermission()
repository.requestNotificationListenerPermission()

Then("알림 설정 화면을 여는 Intent가 시작되어야 한다") {
verify { mockContext.startActivity(capture(intentSlot)) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ class NotificationPermissionUseCaseTest : BehaviorSpec({

When("알림 서비스가 비활성화되어 있다면") {
every { repository.isNotificationServiceEnabled() } returns false
every { repository.requestPermission() } returns Unit
every { repository.requestNotificationListenerPermission() } returns Unit

Then("권한 요청을 해야 한다") {
useCase.requestPermission()
verify { repository.requestPermission() }
verify { repository.requestNotificationListenerPermission() }
}
}
}
Expand All @@ -50,7 +50,7 @@ class NotificationPermissionUseCaseTest : BehaviorSpec({

Then("권한 요청을 하지 않아야 한다") {
useCase.requestPermission()
verify(exactly = 0) { repository.requestPermission() }
verify(exactly = 0) { repository.requestNotificationListenerPermission() }
}
}
}
Expand Down
Loading