Notifications now use AlarmManager instead of WorkManager for delivery, TODO: notifications should be sent even if the app is closed (swiped from 'recents' view)
This commit is contained in:
@@ -54,8 +54,6 @@ dependencies {
|
||||
implementation "androidx.room:room-runtime:2.2.3"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
|
||||
implementation "androidx.work:work-runtime-ktx:2.3.3"
|
||||
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'
|
||||
|
||||
|
||||
Binary file not shown.
@@ -11,8 +11,8 @@
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"properties": [],
|
||||
"versionCode": 1,
|
||||
"versionName": "1",
|
||||
"versionCode": 2,
|
||||
"versionName": "2",
|
||||
"enabled": true,
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme.Launcher">
|
||||
<service android:name=".util.ExamService"
|
||||
android:description="@string/exam_service_description"
|
||||
android:enabled="true"/>
|
||||
<activity android:name=".activity.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
package com.denizd.qwark.activity
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.work.*
|
||||
import com.denizd.lawrence.util.viewBinding
|
||||
import com.denizd.qwark.R
|
||||
import com.denizd.qwark.database.QwarkRepository
|
||||
import com.denizd.qwark.databinding.ActivityMainBinding
|
||||
import com.denizd.qwark.fragment.*
|
||||
import com.denizd.qwark.util.Dependencies
|
||||
import com.denizd.qwark.util.ExamNotificationWorker
|
||||
import com.denizd.qwark.util.ExamService
|
||||
import com.denizd.qwark.util.QwarkUtil
|
||||
import com.denizd.qwark.viewmodel.MainViewModel
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.random.Random
|
||||
|
||||
class MainActivity : FragmentActivity() {
|
||||
@@ -88,16 +92,23 @@ class MainActivity : FragmentActivity() {
|
||||
// }, 1200)
|
||||
|
||||
Dependencies.repo.allCoursesWithExams.observe(this, Observer { courses ->
|
||||
with (WorkManager.getInstance(this)) {
|
||||
with (getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
for (course in courses) {
|
||||
beginUniqueWork(
|
||||
"${course.name}-${course.courseId}",
|
||||
ExistingWorkPolicy.REPLACE,
|
||||
OneTimeWorkRequestBuilder<ExamNotificationWorker>()
|
||||
.setInitialDelay(getTimeUntil(course.examTime), TimeUnit.MILLISECONDS)
|
||||
.setInputData(Data.Builder().putString("course", course.name).build())
|
||||
.build()
|
||||
).enqueue()
|
||||
// val t = getTimeUntil(course.examTime)
|
||||
if (course.examTime > QwarkUtil.timeAtMidnight || !(QwarkUtil.timeAtMidnight + viewModel.getExamNotificationTime()).hasPassed()) {
|
||||
set(
|
||||
AlarmManager.RTC,
|
||||
course.examTime + viewModel.getExamNotificationTime(),
|
||||
PendingIntent.getService(
|
||||
this@MainActivity,
|
||||
course.courseId,
|
||||
Intent(this@MainActivity, ExamService::class.java).also { intent ->
|
||||
intent.putExtra("course", course.name)
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -154,6 +165,6 @@ class MainActivity : FragmentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add option to set time of notification (currently: 7 AM)
|
||||
private fun getTimeUntil(examTime: Long): Long = examTime + viewModel.getExamNotificationTime() - System.currentTimeMillis()
|
||||
private fun Long.hasPassed(): Boolean = this < System.currentTimeMillis()
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ interface QwarkDao {
|
||||
@Query("SELECT course.*, (SELECT MIN(exam_time) FROM grade WHERE grade.course_id = course.course_id AND exam_time >= :time) AS exam_time FROM course GROUP BY course.course_id ORDER BY time")
|
||||
fun getAllCourseExams(time: Long = QwarkUtil.timeAtMidnight): List<CourseExam>
|
||||
|
||||
@Query("SELECT course.*, (SELECT MIN(exam_time) FROM grade WHERE grade.course_id = course.course_id AND exam_time >= :time) AS exam_time FROM course WHERE exam_time > :time GROUP BY course.course_id ORDER BY time")
|
||||
fun getAllCoursesWithExams(time: Long = QwarkUtil.timeAtMidnight + 25200000L): LiveData<List<CourseExam>>
|
||||
@Query("SELECT course.*, (SELECT MIN(exam_time) FROM grade WHERE grade.course_id = course.course_id AND exam_time >= :timeAtMidnight) AS exam_time FROM course WHERE exam_time > -1 GROUP BY course.course_id ORDER BY time")
|
||||
fun getAllCoursesWithExams(timeAtMidnight: Long = QwarkUtil.timeAtMidnight): LiveData<List<CourseExam>>
|
||||
|
||||
@Query("SELECT *, -1 AS exam_time FROM course WHERE course_id != :u ORDER BY time")
|
||||
fun getAllCourses(u: Int = -1): List<CourseExam> // the u variable is an unnecessary workaround to return a list instead of LiveData
|
||||
|
||||
+15
-16
@@ -1,6 +1,7 @@
|
||||
package com.denizd.qwark.util
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.app.IntentService
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
@@ -8,43 +9,40 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.denizd.qwark.R
|
||||
import com.denizd.qwark.activity.MainActivity
|
||||
|
||||
private const val notificationChannelId = "qwark_exam_notification"
|
||||
|
||||
class ExamNotificationWorker(private val context: Context, workerParams: WorkerParameters) : Worker(context.applicationContext, workerParams) {
|
||||
class ExamService : IntentService("ExamService") {
|
||||
|
||||
override fun doWork(): Result {
|
||||
sendNotification(course = inputData.getString("course") ?: "error")
|
||||
return Result.success()
|
||||
override fun onHandleIntent(intent: Intent?) {
|
||||
sendNotification(course = intent?.getStringExtra("course") ?: "error")
|
||||
}
|
||||
|
||||
// TODO launch fragment from intent and launch the fragment for the course
|
||||
private fun sendNotification(course: String) {
|
||||
val openAppPending = PendingIntent.getActivity(
|
||||
context, 0,
|
||||
Intent(context, MainActivity::class.java).also { intent ->
|
||||
this, 0,
|
||||
Intent(this, MainActivity::class.java).also { intent ->
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}, 0
|
||||
)
|
||||
|
||||
val notificationService = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
val notificationService = this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createNotificationChannel(context, notificationService)
|
||||
createNotificationChannel(this, notificationService)
|
||||
}
|
||||
|
||||
val notification = NotificationCompat.Builder(context, notificationChannelId)
|
||||
val notification = NotificationCompat.Builder(this, notificationChannelId)
|
||||
// .setStyle(NotificationCompat.BigTextStyle())
|
||||
.setContentTitle(context.getString(R.string.exam_reminder, course))
|
||||
.setContentText(context.getString(R.string.writing_an_exam_today, course))
|
||||
.setContentTitle(this.getString(R.string.exam_reminder, course))
|
||||
.setContentText(this.getString(R.string.writing_an_exam_today, course))
|
||||
.setContentIntent(openAppPending)
|
||||
.setAutoCancel(true)
|
||||
.setColor(context.getColor(R.color.colorAccent))
|
||||
.setColor(this.getColor(R.color.colorAccent))
|
||||
.setSmallIcon(R.drawable.bolt)
|
||||
.build()
|
||||
|
||||
@@ -54,7 +52,8 @@ class ExamNotificationWorker(private val context: Context, workerParams: WorkerP
|
||||
@TargetApi(26)
|
||||
private fun createNotificationChannel(context: Context, notificationManager: NotificationManager) {
|
||||
if (!Dependencies.repo.prefs.getIsNotificationChannelCreated()) {
|
||||
notificationManager.createNotificationChannel(NotificationChannel(
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(
|
||||
notificationChannelId, context.getString(R.string.exams), NotificationManager.IMPORTANCE_DEFAULT
|
||||
).also { channel ->
|
||||
channel.enableLights(true)
|
||||
@@ -19,6 +19,7 @@
|
||||
<string name="exams">Klausuren</string>
|
||||
<string name="exam_reminder">Klausurerinnerung: %s</string>
|
||||
<string name="writing_an_exam_today">Heute schreibst du eine Klausur in %s!</string>
|
||||
<string name="exam_service_description">Verschickt Benachrichtigungen für anstehende Klausuren</string>
|
||||
|
||||
<!-- CourseFragment.kt -->
|
||||
<string name="course">Kurs</string>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<string name="exams">Exams</string>
|
||||
<string name="exam_reminder">Exam reminder: %s</string>
|
||||
<string name="writing_an_exam_today">You\'re writing an exam in %s today!</string>
|
||||
<string name="exam_service_description">Sends notifications for upcoming exams</string>
|
||||
|
||||
<string-array name="greetings">
|
||||
<item>Hello %s!</item>
|
||||
|
||||
Reference in New Issue
Block a user