Skip to content

Commit

Permalink
[Feat] Notification (#216)
Browse files Browse the repository at this point in the history
* feat: test notify ์„ฑ๊ณต

* add: notify ์ž‘์—… ํŒŒ์ผ ์Šคํ…Œ์ด์ง•

* feat: workManager๋กœ ๊ตฌํ˜„

* chore: modify workManager

* modify: change workManager to AlarmManager

it working on api 28, but not working on api 33

* chore: notify on 11 am

* feat: save notification statue in datastore

* modify: change mypage design

* chore: modify layout

* chore: modify code

* chore: modify code

* delete: work manager

* chore: change alarm logo file to vector

* chore: move code loading app version

* chore: change padding

* chore: separate setting alarm code at UI

* chore: at 11
  • Loading branch information
HI-JIN2 authored Sep 26, 2024
1 parent 96c78ac commit 7098028
Show file tree
Hide file tree
Showing 24 changed files with 624 additions and 190 deletions.
7 changes: 4 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ android {
namespace = "com.eatssu.android"
compileSdk = 34

// S8: API 28
// S21: API 33
defaultConfig {
applicationId = "com.eatssu.android"
minSdk = 23
targetSdk = 34
versionCode = 19
versionName = "2.0.0"
versionCode = 20
versionName = "2.1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

Expand Down Expand Up @@ -145,7 +147,6 @@ dependencies {
implementation(libs.firebase.analytics)
implementation(libs.firebase.crashlytics)


// Timber for logging
implementation(libs.timber)
}
Expand Down
20 changes: 0 additions & 20 deletions app/release/output-metadata.json

This file was deleted.

17 changes: 16 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<!-- ์ด๋ฏธ์ง€ ๊ด€๋ จ -->
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
Expand All @@ -17,11 +18,15 @@
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />

<uses-feature
android:name="android.hardware.camera"
android:required="true" />

<!-- ์•Œ๋ฆผ ๊ด€๋ จ -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

<application
android:name=".App"
android:allowBackup="true"
Expand All @@ -36,6 +41,16 @@
android:theme="@style/Theme.EatSSUAndroid"
android:usesCleartextTraffic="true"
tools:targetApi="31">

<receiver
android:name=".util.NotificationReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

<activity
android:name=".ui.mypage.DeveloperActivity"
android:exported="false" />
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/eatssu/android/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import timber.log.Timber
@HiltAndroidApp
class App: Application() {
companion object{
lateinit var appContext : Context
lateinit var appContext: Context //todo ์ด๊ฑฐ ๋นผ๊ธฐ
}

override fun onCreate() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// PreferencesRepository.kt
package com.eatssu.android.data.repository

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class PreferencesRepository(private val context: Context) {

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

companion object {
private val DAILY_NOTIFICATION_KEY = booleanPreferencesKey("daily_notification")
}

val dailyNotificationStatus: Flow<Boolean> = context.dataStore.data
.map { preferences ->
preferences[DAILY_NOTIFICATION_KEY] ?: false // Default value is false
}

suspend fun setDailyNotificationStatus(status: Boolean) {
context.dataStore.edit { preferences ->
preferences[DAILY_NOTIFICATION_KEY] = status
}
}
}
44 changes: 44 additions & 0 deletions app/src/main/java/com/eatssu/android/data/usecase/AlarmUsecase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.eatssu.android.data.usecase

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import com.eatssu.android.util.NotificationReceiver
import java.util.Calendar
import javax.inject.Inject

class AlarmUseCase @Inject constructor(private val context: Context) {

fun scheduleAlarm() {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, NotificationReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

val calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, 11)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}

if (calendar.timeInMillis <= System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 1)
}

alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP, calendar.timeInMillis, AlarmManager.INTERVAL_DAY, pendingIntent
)
}

fun cancelAlarm() {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, NotificationReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
alarmManager.cancel(pendingIntent)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.eatssu.android.data.usecase

import com.eatssu.android.data.repository.PreferencesRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class GetDailyNotificationStatusUseCase @Inject constructor(
private val preferencesRepository: PreferencesRepository
) {
operator fun invoke(): Flow<Boolean> {
return preferencesRepository.dailyNotificationStatus
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.eatssu.android.data.usecase

import com.eatssu.android.data.repository.PreferencesRepository
import javax.inject.Inject


class SetDailyNotificationStatusUseCase @Inject constructor(
private val preferencesRepository: PreferencesRepository
) {
suspend operator fun invoke(status: Boolean) {
preferencesRepository.setDailyNotificationStatus(status)
}
}
28 changes: 28 additions & 0 deletions app/src/main/java/com/eatssu/android/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.eatssu.android.di

import android.app.Application
import android.content.Context
import com.eatssu.android.data.repository.PreferencesRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

@Provides
@Singleton
fun provideContext(application: Application): Context {
return application.applicationContext
}

@Provides
@Singleton
fun providePreferencesRepository(@ApplicationContext context: Context): PreferencesRepository {
return PreferencesRepository(context)
}
}
50 changes: 48 additions & 2 deletions app/src/main/java/com/eatssu/android/ui/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.eatssu.android.ui.main

import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.view.Menu
Expand All @@ -10,6 +11,8 @@ import android.view.View
import android.widget.TextView
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
Expand All @@ -22,6 +25,7 @@ import com.eatssu.android.ui.main.calendar.CalendarAdapter
import com.eatssu.android.ui.main.calendar.CalendarAdapter.OnItemListener
import com.eatssu.android.ui.main.calendar.CalendarViewModel
import com.eatssu.android.ui.mypage.MyPageActivity
import com.eatssu.android.ui.mypage.MyPageViewModel
import com.eatssu.android.ui.mypage.usernamechange.UserNameChangeActivity
import com.eatssu.android.util.CalendarUtils
import com.eatssu.android.util.CalendarUtils.daysInWeekArray
Expand All @@ -30,18 +34,20 @@ import com.eatssu.android.util.extension.showToast
import com.eatssu.android.util.extension.startActivity
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.prolificinteractive.materialcalendarview.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import timber.log.Timber
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.util.*
import java.util.Locale

@AndroidEntryPoint
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate), OnItemListener {

private val mainViewModel: MainViewModel by viewModels()
private val myPageViewModel: MyPageViewModel by viewModels()


private lateinit var calendarViewModel: CalendarViewModel

Expand All @@ -57,6 +63,24 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl

setupNoToolbar()

// ์•Œ๋ฆผ ํผ๋ฏธ์…˜ ์žˆ๋Š”์ง€ ์ž๊ฐ€ ์ง„๋‹จ
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
// ๊ถŒํ•œ์ด ์—†๋‹ค๋ฉด ์š”์ฒญ
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
1000
)
} else {
// ๊ถŒํ•œ์ด ์ด๋ฏธ ์žˆ์–ด
}
}

checkNicknameIsNull()

// 1) ViewPager2 ์ฐธ์กฐ
Expand Down Expand Up @@ -192,4 +216,26 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
}
}

// ๊ถŒํ•œ ์š”์ฒญ ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)

val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault())

if (requestCode == 1000) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// ๊ถŒํ•œ์ด ์Šน์ธ๋จ
showToast("EAT-SSU ์•Œ๋ฆผ ์ˆ˜์‹ ์„ ๋™์˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค.")
myPageViewModel.setNotificationOn() //๋ฐ”๋กœ ์•Œ๋ฆผ ๋ฐ›๋„๋ก ์„ค์ •
} else {
// ๊ถŒํ•œ์ด ๊ฑฐ๋ถ€๋จ
showToast("EAT-SSU ์•Œ๋ฆผ ์ˆ˜์‹ ์„ ๊ฑฐ๋ถ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค.\n$dateFormat")
myPageViewModel.setNotificationOff() //๋ฐ”๋กœ ์•Œ๋ฆผ ๋ฐ›๋„๋ก ์„ค์ •
}
}
}
}
Loading

0 comments on commit 7098028

Please sign in to comment.