diff --git a/app/src/main/java/com/example/notimanager/data/source/local/database/NotiManagerDatabase.kt b/app/src/main/java/com/example/notimanager/data/source/local/database/NotiManagerDatabase.kt index e2bdf79..d421594 100644 --- a/app/src/main/java/com/example/notimanager/data/source/local/database/NotiManagerDatabase.kt +++ b/app/src/main/java/com/example/notimanager/data/source/local/database/NotiManagerDatabase.kt @@ -31,9 +31,9 @@ import com.example.notimanager.data.source.local.database.MigrationObject.MIGRAT AppIconModel::class, FilteredNotificationModel::class ], - autoMigrations = [ - AutoMigration (from = 9, to = 10) - ] +// autoMigrations = [ +// AutoMigration (from = 9, to = 10) +// ] ) abstract class NotiManagerDatabase : RoomDatabase() { abstract fun notificationDao(): NotificationDao 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 index 8289a5d..97689bf 100644 --- a/app/src/main/java/com/example/notimanager/domain/service/ForegroundNotiService.kt +++ b/app/src/main/java/com/example/notimanager/domain/service/ForegroundNotiService.kt @@ -55,7 +55,7 @@ class ForegroundNotiService: Service() { } val pendingIntent = PendingIntent .getActivity(this, - 0, + appName.hashCode(), notificationIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT) 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 2f04411..d431394 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 @@ -41,6 +41,7 @@ class NotiListenerService: NotificationListenerService() { val postTime = sbn.postTime CoroutineScope(Dispatchers.IO).launch { + if (appName == "NotiManager") return@launch if (title == "" && content == "") return@launch val filteredList = filterRepository.getSpecificFilteredList(appName, title, subText) 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 733873f..4ecf318 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 @@ -13,9 +13,7 @@ class NotificationPermissionUseCase( } fun requestPermission() { - if (!repository.isNotificationServiceEnabled()) { - repository.requestNotificationListenerPermission() - } + repository.requestNotificationListenerPermission() } fun isNotificationPermissionGranted(): Boolean{ 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 2501f0b..f79ca59 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,30 +1,41 @@ package com.example.notimanager.presentation.stateholder.viewmodel import android.app.Activity -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.provider.Settings +import android.util.Log import androidx.lifecycle.ViewModel import com.example.notimanager.domain.usecase.NotificationPermissionUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject @HiltViewModel class NotificationPermissionViewModel @Inject constructor( + @ApplicationContext private val appContext: Context, private val notificationPermissionUseCase: NotificationPermissionUseCase ) : ViewModel() { + private val prefs = "do_permission" + private val sharedPreferences = appContext.getSharedPreferences(prefs, Context.MODE_PRIVATE) - private val _isNotificationPermissionGranted = MutableLiveData() - val isNotificationPermissionGranted: LiveData get() = _isNotificationPermissionGranted - - init { - checkNotificationPermission() + fun requestPermission(activity: Activity) { + if (!checkNotificationPermission()) { + notificationPermissionUseCase.requestPermission(activity) + sharedPreferences.edit().putBoolean(prefs, true).apply() + } + else openAppSettings(activity) } - fun checkNotificationPermission() { - _isNotificationPermissionGranted.value = notificationPermissionUseCase.isNotificationPermissionGranted() + fun checkNotificationPermission(): Boolean { + return sharedPreferences.getBoolean(prefs, false) } - fun requestPermission(activity: Activity) { - notificationPermissionUseCase.requestPermission(activity) + private fun openAppSettings(activity: Activity) { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + val uri = Uri.fromParts("package", activity.packageName, null) + intent.data = uri + activity.startActivity(intent) } } 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 0f7e926..56d3447 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 @@ -2,11 +2,9 @@ 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.compose.ui.platform.LocalContext import androidx.navigation.NavController import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController @@ -26,10 +24,11 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // 언어 변경에 따라 문자열 리소스를 가져오기 + // 언어 설정에 따라 문자열 리소스를 가져오기 val basicTitle = getString(R.string.status_basic_title) val basicContent = getString(R.string.status_basic_content) + // 화면 설정 val appName = intent.extras?.getString("appName") ?: "" setContent { navController = rememberNavController() @@ -37,13 +36,13 @@ class MainActivity : ComponentActivity() { if (appName != "" && appName != "NotiManager") navController.navigate("titleScreen/$appName") } - notificationViewModel.isNotificationPermissionGranted.observe(this) { isGranted -> - if (!isGranted) { - notificationViewModel.requestPermission(this) - } + // 알림 허용 권한 요청 + if (!notificationViewModel.checkNotificationPermission()){ + notificationViewModel.requestPermission(this) } + + // 포그라운드 서비스 실행 val serviceIntent = Intent(this, ForegroundNotiService::class.java).apply { - putExtra("clearGroup", true) putExtra("appName", basicTitle) putExtra("content", basicContent) putExtra("isGroupSummary", true) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/FilteredListView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/FilteredListView.kt index 88b4a38..794f0c7 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/FilteredListView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/FilteredListView.kt @@ -59,10 +59,9 @@ fun FilteredItemView( filteredItem: FilteredNotification, viewModel: FilteredNotificationViewModel, ) { - // 언어 변경에 따라 문자열 리소스를 가져오기 + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val removeFiltered = context.getString(R.string.modal_remove_filtered) - // 위의 문자열 리소스는 모달에서 사용할 텍스트 var showModal by remember { mutableStateOf(false) } diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt index c9ac139..65885a5 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt @@ -111,7 +111,7 @@ fun NotificationAppItemView( priorityViewModel: NotificationAppPriorityViewModel, filteredNotificationViewModel: FilteredNotificationViewModel = hiltViewModel() ) { - // 언어 변경에 따라 문자열 리소스를 가져오기 + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val addFiltered = context.getString(R.string.modal_add_filtered) val addPriority = context.getString(R.string.modal_add_priority) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt index 4001a45..b0b7602 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt @@ -63,7 +63,7 @@ fun NotificationItemView( onClick: () -> Unit, onDelete: (Long) -> Unit ) { - // 언어 변경에 따라 문자열 리소스를 가져오기 + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val moveToApp = context.getString(R.string.modal_move_to_app) val delete = context.getString(R.string.modal_delete) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt index 8e56239..4d7e3e4 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt @@ -122,7 +122,7 @@ fun NotificationTitleItemView( priorityViewModel: NotificationTitlePriorityViewModel, filteredNotificationViewModel: FilteredNotificationViewModel = hiltViewModel() ) { - // 언어 변경에 따라 문자열 리소스를 가져오기 + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val addFiltered = context.getString(R.string.modal_add_filtered) val addPriority = context.getString(R.string.modal_add_priority) 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 33e1c16..08b1c5b 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 @@ -16,6 +16,7 @@ import com.example.notimanager.presentation.stateholder.viewmodel.NotificationSe @Composable fun PermissionCheck(viewModel: NotificationServicePermissionViewModel = hiltViewModel()){ + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val title = context.getString(R.string.permission_title) val message = context.getString(R.string.permission_message) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/SettingView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/SettingView.kt index 4f2d933..2d3bbbe 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/SettingView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/SettingView.kt @@ -1,27 +1,46 @@ package com.example.notimanager.presentation.ui.component +import android.app.Activity import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.example.notimanager.R +import com.example.notimanager.presentation.stateholder.viewmodel.NotificationPermissionViewModel +import com.example.notimanager.presentation.stateholder.viewmodel.NotificationServicePermissionViewModel @Composable fun SettingView( innerPadding: PaddingValues, - navController: NavController -){ + navController: NavController, + servicePermissionViewModel: NotificationServicePermissionViewModel = hiltViewModel(), + notificationPermissionViewModel: NotificationPermissionViewModel = hiltViewModel(), + + ){ + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current - val name = context.getString(R.string.setting_filtered_list) + val filteredList = context.getString(R.string.setting_filtered_list) + val accessPermission = context.getString(R.string.setting_access_permission) + val sendPermission = context.getString(R.string.setting_send_permission) + Column( modifier = Modifier .padding(innerPadding) ) { - ClickableTextView(name) { + ClickableTextView(filteredList) { navController.navigate("FilteredListScreen") } + + ClickableTextView(accessPermission) { + servicePermissionViewModel.requestServicePermission() + } + + ClickableTextView(sendPermission) { + notificationPermissionViewModel.requestPermission(context as Activity) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt index 01947e3..d2b1e98 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt @@ -18,8 +18,10 @@ import com.example.notimanager.R @OptIn(ExperimentalMaterial3Api::class) @Composable fun MainTopAppBar(settingOnClick: () -> Unit){ + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val appName = context.getString(R.string.app_name) + TopAppBar( title = { Text(text = appName) @@ -73,8 +75,10 @@ fun NotificationTopAppBar(title: String, onBackClick: () -> Unit){ @OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingTopAppBar(onBackClick: () -> Unit){ + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val name = context.getString(R.string.setting_name) + TopAppBar( title = { Text(text = name) @@ -90,8 +94,10 @@ fun SettingTopAppBar(onBackClick: () -> Unit){ @OptIn(ExperimentalMaterial3Api::class) @Composable fun FilteredTopAppBar(onBackClick: () -> Unit){ + // 언어 설정에 따라 문자열 리소스를 가져오기 val context = LocalContext.current val name = context.getString(R.string.setting_filtered_list) + TopAppBar( title = { Text(text = name) diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 9c04881..bd405f7 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -5,25 +5,27 @@ 삭제 앱으로 이동하기 - 더 이상 알림 받지 않기 - 상단에 고정하기 + 앱에서 이 알림 관리하지 않기 + 중요 알림으로 설정하기 읽음으로 표시하기 읽지 않음으로 표시하기 - 다시 알림 받기"> - 고정 취소하기 + 앱에서 이 알림 관리하기"> + 중요 알림 설정 취소하기 설정 - 받지 않는 알림 목록 + 관리하지 않는 알림 목록 언어 설정하기 + 알림 접근 권한 변경하기 + 알림 발송 권한 변경하기 확인 거부 - 알림 권한이 필요해요 - 알림을 받기 위해 알림 권한이 필요해요 + 알림 접근 권한이 필요해요 + 앱에서 알림을 관리하기 위해 권한을 허용해주세요. NotiManager diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 73f45e2..b4ae42d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,29 +1,32 @@ NotiManager - + Delete Move to App - Stop Receiving Notifications - Pin to Top + Do not manage this notification in the app + Set as Important Notification Mark as Read Mark as Unread - Start Receiving Notifications Again - Unpin + Manage this notification in the app + Cancel Important Notification Setting - + Settings - List of Notifications Not Received - Change Language + List of Unmanaged Notifications + Change Language Settings + Change Notification Access Permission + Change Notification Send Permission - + + OK Deny - Notification Permission Required - Notification permission is required to receive notifications. + Notification Access Permission Required + Please allow permission to manage notifications in the app. NotiManager 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 c61b808..11bd86c 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 @@ -45,13 +45,5 @@ class NotificationPermissionUseCaseTest : BehaviorSpec({ } } - When("알림 서비스가 이미 활성화되어 있다면") { - every { repository.isNotificationServiceEnabled() } returns true - - Then("권한 요청을 하지 않아야 한다") { - useCase.requestPermission() - verify(exactly = 0) { repository.requestNotificationListenerPermission() } - } - } } })