periodic notification

This commit is contained in:
ImAliant 2024-01-05 03:16:09 +01:00
parent d1337113e9
commit 10b207e3f5
8 changed files with 134 additions and 2 deletions

View file

@ -60,6 +60,7 @@ dependencies {
implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3") implementation("androidx.compose.material3:material3")
implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.work:work-runtime-ktx:2.8.1")
val roomVersion = "2.6.0" val roomVersion = "2.6.0"
implementation("androidx.room:room-runtime:$roomVersion") implementation("androidx.room:room-runtime:$roomVersion")

View file

@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application <application
android:name=".MemoApplication" android:name=".MemoApplication"
@ -18,7 +19,6 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.MemorisationApplication"> android:theme="@style/Theme.MemorisationApplication">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View file

@ -61,7 +61,7 @@ fun MainScreenMainActivity() {
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
fun MainScreenActivityPreview() { fun MainScreenPreview() {
MainScreen() MainScreen()
} }

View file

@ -1,8 +1,70 @@
package fr.uparis.diamantkennel.memorisationapplication package fr.uparis.diamantkennel.memorisationapplication
import android.app.Application import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import fr.uparis.diamantkennel.memorisationapplication.data.QuestionsDB import fr.uparis.diamantkennel.memorisationapplication.data.QuestionsDB
import java.util.Calendar
import java.util.concurrent.TimeUnit
const val CHANNEL_ID = "MY_CHANNEL_ID"
class MemoApplication : Application() { class MemoApplication : Application() {
val database: QuestionsDB by lazy { QuestionsDB.getDataBase(this) } val database: QuestionsDB by lazy { QuestionsDB.getDataBase(this) }
override fun onCreate() {
super.onCreate()
createChannel(this)
if (this.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED)
schedule()
else
Log.d("MemoApplication", "onCreate: no permission")
}
private fun createChannel(c: Context)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
val name = "MY_CHANNEL"
val descriptionText = "notification channel for Memorisation project"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
val notificationManager = c.getSystemService(Context.NOTIFICATION_SERVICE)
as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
private fun schedule()
{
val wm = WorkManager.getInstance(this)
wm.cancelAllWork()
wm.enqueue(request(10, 45))
}
private fun request(h: Int, m: Int): PeriodicWorkRequest
{
val now = Calendar.getInstance()
val target = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, h)
set(Calendar.MINUTE, m)
}
if (target.before(now))
target.add(Calendar.DAY_OF_YEAR, 1)
val delta=target.timeInMillis - now.timeInMillis
val request = PeriodicWorkRequest.Builder(RappelWorker::class.java, 1, TimeUnit.DAYS)
.setInitialDelay(delta, TimeUnit.MILLISECONDS)
.build()
Log.d("Periodic", "request: $request")
return request
}
} }

View file

@ -0,0 +1,37 @@
package fr.uparis.diamantkennel.memorisationapplication
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.work.Worker
import androidx.work.WorkerParameters
class RappelWorker(private val context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
override fun doWork(): Result {
createNotification(context)
return Result.success()
}
private fun createNotification(context: Context)
{
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
)
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Rappel")
.setContentText("Il est temps de réviser !")
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
val notification = builder.build()
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE)
as NotificationManager
notificationManager.notify(0, notification)
}
}

View file

@ -1,5 +1,8 @@
package fr.uparis.diamantkennel.memorisationapplication package fr.uparis.diamantkennel.memorisationapplication
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
@ -33,6 +36,12 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
var deletionDBRequest by model.deletionDB var deletionDBRequest by model.deletionDB
var cleanStatRequest by model.deletionStat var cleanStatRequest by model.deletionStat
val permissionLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
) {
Log.d("permissions", if(it) "granted" else "denied")
}
if (deletionDBRequest) { if (deletionDBRequest) {
DeletionDBDialog(model::deleteDb) { deletionDBRequest = false } DeletionDBDialog(model::deleteDb) { deletionDBRequest = false }
} }
@ -70,6 +79,15 @@ fun SettingsScreen(padding: PaddingValues, model: SettingsViewModel = viewModel(
Text(text = context.getString(R.string.clean_stat_button)) Text(text = context.getString(R.string.clean_stat_button))
} }
} }
Button(
enabled = model.isNotGranted(context),
onClick = {
model.requestNotificationPermission(permissionLauncher)
}
) {
Text(text = context.getString(R.string.permission_button))
}
} }
} }

View file

@ -1,6 +1,9 @@
package fr.uparis.diamantkennel.memorisationapplication.ui package fr.uparis.diamantkennel.memorisationapplication.ui
import android.app.Application import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import androidx.activity.result.ActivityResultLauncher
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.intPreferencesKey
@ -59,4 +62,14 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
} }
return ((good.toFloat() / total.toFloat()) * 100).toInt() return ((good.toFloat() / total.toFloat()) * 100).toInt()
} }
fun requestNotificationPermission(launcher: ActivityResultLauncher<String>)
{
launcher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
}
fun isNotGranted(context: Context): Boolean
{
return context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
}
} }

View file

@ -50,4 +50,5 @@
<string name="clean_stat_button">Réinitialiser stats</string> <string name="clean_stat_button">Réinitialiser stats</string>
<string name="clean_stat">Réinitialiser les statistiques</string> <string name="clean_stat">Réinitialiser les statistiques</string>
<string name="clean_stat_desc">Voulez-vous réinitialiser les statistiques ?</string> <string name="clean_stat_desc">Voulez-vous réinitialiser les statistiques ?</string>
<string name="permission_button">Autoriser notification</string>
</resources> </resources>