diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f7d40df..6f088d8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + = Build.VERSION_CODES.TIRAMISU) { + appContext.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } else { + true + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/di/AppModule.kt b/app/src/main/java/com/example/notimanager/di/AppModule.kt index 261ecbf..6efe0ff 100644 --- a/app/src/main/java/com/example/notimanager/di/AppModule.kt +++ b/app/src/main/java/com/example/notimanager/di/AppModule.kt @@ -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 @@ -15,7 +15,7 @@ class AppModule { @Singleton fun provideNotificationPermissionViewModel( notificationPermissionUseCase: NotificationPermissionUseCase - ): NotificationPermissionViewModel { - return NotificationPermissionViewModel(notificationPermissionUseCase) + ): NotificationServicePermissionViewModel { + return NotificationServicePermissionViewModel(notificationPermissionUseCase) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/domain/repository/NotificationPermissionRepositoryInterface.kt b/app/src/main/java/com/example/notimanager/domain/repository/NotificationPermissionRepositoryInterface.kt index e43f19c..3af3b01 100644 --- a/app/src/main/java/com/example/notimanager/domain/repository/NotificationPermissionRepositoryInterface.kt +++ b/app/src/main/java/com/example/notimanager/domain/repository/NotificationPermissionRepositoryInterface.kt @@ -2,5 +2,6 @@ package com.example.notimanager.domain.repository interface NotificationPermissionRepositoryInterface { fun isNotificationServiceEnabled(): Boolean - fun requestPermission() + fun requestNotificationListenerPermission() + fun isNotificationPermissionGranted(): Boolean } \ 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 be61606..5010f69 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 @@ -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 diff --git a/app/src/main/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCase.kt b/app/src/main/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCase.kt index 7c3d2a2..733873f 100644 --- a/app/src/main/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCase.kt +++ b/app/src/main/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCase.kt @@ -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( @@ -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 + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/presentation/stateholder/viewmodel/NotificationPermissionViewModel.kt b/app/src/main/java/com/example/notimanager/presentation/stateholder/viewmodel/NotificationPermissionViewModel.kt index 54950fd..2501f0b 100644 --- a/app/src/main/java/com/example/notimanager/presentation/stateholder/viewmodel/NotificationPermissionViewModel.kt +++ b/app/src/main/java/com/example/notimanager/presentation/stateholder/viewmodel/NotificationPermissionViewModel.kt @@ -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 @@ -12,19 +13,18 @@ class NotificationPermissionViewModel @Inject constructor( private val notificationPermissionUseCase: NotificationPermissionUseCase ) : ViewModel() { - private val _isPermissionGranted = MutableLiveData() - val isPermissionGranted: LiveData get() = _isPermissionGranted + private val _isNotificationPermissionGranted = MutableLiveData() + val isNotificationPermissionGranted: LiveData 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) } } diff --git a/app/src/main/java/com/example/notimanager/presentation/stateholder/viewmodel/NotificationServicePermissionViewModel.kt b/app/src/main/java/com/example/notimanager/presentation/stateholder/viewmodel/NotificationServicePermissionViewModel.kt new file mode 100644 index 0000000..f37db9a --- /dev/null +++ b/app/src/main/java/com/example/notimanager/presentation/stateholder/viewmodel/NotificationServicePermissionViewModel.kt @@ -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() + val isNotificationServiceEnabled: LiveData get() = _isNotificationServiceEnabled + + init { + checkNotificationServicePermission() + } + + fun checkNotificationServicePermission() { + _isNotificationServiceEnabled.value = notificationPermissionUseCase.isNotificationServiceEnabled() + } + + fun requestServicePermission() { + notificationPermissionUseCase.requestPermission() + checkNotificationServicePermission() + } +} 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 7969b4c..55243fd 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 @@ -6,13 +6,14 @@ 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) @@ -20,11 +21,16 @@ class MainActivity : ComponentActivity() { setContent { AppNavHost(navController = rememberNavController()) } + + notificationViewModel.isNotificationPermissionGranted.observe(this) { isGranted -> + if (!isGranted) { + notificationViewModel.requestPermission(this) + } + } } override fun onResume() { super.onResume() - viewModel.checkNotificationPermission() + serviceViewModel.checkNotificationServicePermission() } - } diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/PermissionDialog.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/PermissionDialog.kt index 5689caf..f7dd5ff 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/PermissionDialog.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/PermissionDialog.kt @@ -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() }, ) } } diff --git a/app/src/test/java/com/example/notimanager/data/repository/NotificationPermissionTest.kt b/app/src/test/java/com/example/notimanager/data/repository/NotificationPermissionTest.kt index 1504478..6d9b0d6 100644 --- a/app/src/test/java/com/example/notimanager/data/repository/NotificationPermissionTest.kt +++ b/app/src/test/java/com/example/notimanager/data/repository/NotificationPermissionTest.kt @@ -71,7 +71,7 @@ class NotificationPermissionRepositoryTest : BehaviorSpec({ val intentSlot = slot() When("requestPermission 호출") { - repository.requestPermission() + repository.requestNotificationListenerPermission() Then("알림 설정 화면을 여는 Intent가 시작되어야 한다") { verify { mockContext.startActivity(capture(intentSlot)) } diff --git a/app/src/test/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCaseTest.kt b/app/src/test/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCaseTest.kt index 29c25f6..c61b808 100644 --- a/app/src/test/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCaseTest.kt +++ b/app/src/test/java/com/example/notimanager/domain/usecase/NotificationPermissionUseCaseTest.kt @@ -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() } } } } @@ -50,7 +50,7 @@ class NotificationPermissionUseCaseTest : BehaviorSpec({ Then("권한 요청을 하지 않아야 한다") { useCase.requestPermission() - verify(exactly = 0) { repository.requestPermission() } + verify(exactly = 0) { repository.requestNotificationListenerPermission() } } } }