From 0414d69e9cd5b2941cf9c427f17a39d4efd8eb48 Mon Sep 17 00:00:00 2001 From: Ray Jang <48707913+ajou4095@users.noreply.github.com> Date: Mon, 5 Feb 2024 00:45:43 +0900 Subject: [PATCH] [Setting] NotificationUtil (#41) --- .../android/BookkeepingApplication.kt | 37 ++++++++++ presentation/src/main/AndroidManifest.xml | 2 + .../android/presentation/common/Constants.kt | 3 + .../common/util/NotificationUtil.kt | 72 +++++++++++++++++++ .../ui/main/home/setting/SettingScreen.kt | 23 ++++++ 5 files changed, 137 insertions(+) create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/common/util/NotificationUtil.kt diff --git a/app/src/main/kotlin/ac/dnd/bookkeeping/android/BookkeepingApplication.kt b/app/src/main/kotlin/ac/dnd/bookkeeping/android/BookkeepingApplication.kt index 3ed24b38..6f60bd53 100644 --- a/app/src/main/kotlin/ac/dnd/bookkeeping/android/BookkeepingApplication.kt +++ b/app/src/main/kotlin/ac/dnd/bookkeeping/android/BookkeepingApplication.kt @@ -1,6 +1,14 @@ package ac.dnd.bookkeeping.android +import ac.dnd.bookkeeping.android.presentation.common.CHANNEL_1 +import ac.dnd.bookkeeping.android.presentation.common.CHANNEL_GROUP_1 import android.app.Application +import android.app.NotificationChannel +import android.app.NotificationChannelGroup +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import androidx.annotation.RequiresApi import com.kakao.sdk.common.KakaoSdk import dagger.hilt.android.HiltAndroidApp @@ -9,5 +17,34 @@ open class BookkeepingApplication : Application() { override fun onCreate() { super.onCreate() KakaoSdk.init(this, BuildConfig.KAKAO_APP_KEY) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + initializeChannel(this) + } + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun initializeChannel( + context: Context + ) { + val channel1 = NotificationChannel( + CHANNEL_1, + "channel 1", + NotificationManager.IMPORTANCE_HIGH + ).apply { + description = "This is channel 1" + } + + val group = NotificationChannelGroup( + CHANNEL_GROUP_1, + "group 1" + ).apply { + channels.add(channel1) + } + + context.getSystemService(NotificationManager::class.java).run { + createNotificationChannel(channel1) + createNotificationChannelGroup(group) + } } } diff --git a/presentation/src/main/AndroidManifest.xml b/presentation/src/main/AndroidManifest.xml index 589f0303..e53bc6b7 100644 --- a/presentation/src/main/AndroidManifest.xml +++ b/presentation/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + + = Build.VERSION_CODES.TIRAMISU) { + TedPermission + .create() + .setPermissions(Manifest.permission.POST_NOTIFICATIONS) + .check().isGranted + } else { + false + } +} + +private suspend fun Context.checkNotificationChannelEnabled( + id: String +): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val manager = getSystemService(NotificationManager::class.java) + val channel = manager.getNotificationChannel(id) ?: return false + val isChannelEnabled = channel.importance != NotificationManager.IMPORTANCE_NONE + + if (!isChannelEnabled) { + val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply { + putExtra(Settings.EXTRA_APP_PACKAGE, packageName) + putExtra(Settings.EXTRA_CHANNEL_ID, id) + } + startActivity(intent) + } + return isChannelEnabled + } else { + true + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/setting/SettingScreen.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/setting/SettingScreen.kt index 2ba35f46..ae2e8b73 100644 --- a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/setting/SettingScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/setting/SettingScreen.kt @@ -1,9 +1,11 @@ package ac.dnd.bookkeeping.android.presentation.ui.main.home.setting import ac.dnd.bookkeeping.android.presentation.R +import ac.dnd.bookkeeping.android.presentation.common.CHANNEL_1 import ac.dnd.bookkeeping.android.presentation.common.theme.Body1 import ac.dnd.bookkeeping.android.presentation.common.theme.Negative import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver +import ac.dnd.bookkeeping.android.presentation.common.util.showNotification import ac.dnd.bookkeeping.android.presentation.common.view.BottomSheetScreen import ac.dnd.bookkeeping.android.presentation.common.view.DialogScreen import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButton @@ -32,15 +34,18 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import kotlinx.coroutines.launch import timber.log.Timber @Composable @@ -49,6 +54,8 @@ fun SettingScreen( onShowSnackBar: () -> Unit, viewModel: SettingViewModel = hiltViewModel() ) { + val scope = rememberCoroutineScope() + val context = LocalContext.current Observer( appState = appState, viewModel = viewModel @@ -158,6 +165,22 @@ fun SettingScreen( isAddGroupShowing = true } ) + Text( + text = "Notification", + fontSize = 20.sp, + color = Color.Black, + modifier = Modifier + .padding(vertical = 10.dp) + .clickable { + scope.launch { + context.showNotification( + channelId = CHANNEL_1, + title = "title", + content = "content" + ) + } + } + ) } if (isSearchRelationShowing) {