diff --git a/app/build.gradle b/app/build.gradle
index c37e69c..330d85c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -44,6 +44,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.1.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.1.0'
+ implementation "androidx.work:work-runtime-ktx:2.2.0"
implementation "androidx.room:room-runtime:2.2.0-rc01"
kapt "androidx.room:room-compiler:2.2.0-rc01"
implementation "androidx.room:room-ktx:2.2.0-rc01"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 100aeb2..174589e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,6 +20,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/net/underdesk/circolapp/BootCompleteReceiver.kt b/app/src/main/java/net/underdesk/circolapp/BootCompleteReceiver.kt
new file mode 100644
index 0000000..de68cf2
--- /dev/null
+++ b/app/src/main/java/net/underdesk/circolapp/BootCompleteReceiver.kt
@@ -0,0 +1,32 @@
+/*
+ * Circolapp
+ * Copyright (C) 2019 Matteo Schiff
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package net.underdesk.circolapp
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import net.underdesk.circolapp.works.PollWork
+
+
+class BootCompleteReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action == null || intent.action != "android.intent.action.BOOT_COMPLETED") return
+ PollWork.enqueue(context)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/underdesk/circolapp/MainActivity.kt b/app/src/main/java/net/underdesk/circolapp/MainActivity.kt
index e0a5be6..ca7b476 100644
--- a/app/src/main/java/net/underdesk/circolapp/MainActivity.kt
+++ b/app/src/main/java/net/underdesk/circolapp/MainActivity.kt
@@ -25,6 +25,7 @@ import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.bottomnavigation.BottomNavigationView
+import net.underdesk.circolapp.works.PollWork
class MainActivity : AppCompatActivity() {
@@ -45,5 +46,7 @@ class MainActivity : AppCompatActivity() {
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
+
+ PollWork.enqueue(this)
}
}
diff --git a/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt
new file mode 100644
index 0000000..ad6983c
--- /dev/null
+++ b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt
@@ -0,0 +1,128 @@
+/*
+ * Circolapp
+ * Copyright (C) 2019 Matteo Schiff
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package net.underdesk.circolapp.works
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import androidx.work.*
+import net.underdesk.circolapp.MainActivity
+import net.underdesk.circolapp.R
+import net.underdesk.circolapp.data.AppDatabase
+import net.underdesk.circolapp.data.Circular
+import net.underdesk.circolapp.server.DataFetcher
+import java.util.concurrent.TimeUnit
+
+
+class PollWork(appContext: Context, workerParams: WorkerParameters) :
+ Worker(appContext, workerParams) {
+
+ companion object {
+ const val CHANNEL_ID = "net.underdesk.circolapp.NEW_CIRCULAR"
+
+ private const val pollWorkName = "net.underdesk.circolapp.POLL_WORK"
+ private const val repeatIntervalMin: Long = 30
+ private const val flexIntervalMin: Long = 10
+
+ private fun getPollWorkRequest(): PeriodicWorkRequest {
+ val constraints = Constraints.Builder()
+ .setRequiredNetworkType(NetworkType.CONNECTED)
+ .build()
+
+ return PeriodicWorkRequestBuilder(
+ repeatIntervalMin,
+ TimeUnit.MINUTES,
+ flexIntervalMin,
+ TimeUnit.MINUTES
+ ).setConstraints(constraints).build()
+ }
+
+ fun enqueue(context: Context) {
+ WorkManager.getInstance(context)
+ .enqueueUniquePeriodicWork(
+ pollWorkName,
+ ExistingPeriodicWorkPolicy.KEEP,
+ getPollWorkRequest()
+ )
+ }
+ }
+
+ override fun doWork(): Result {
+ val fetcher = DataFetcher()
+
+ val oldCirculars = AppDatabase.getInstance(applicationContext).circularDao().getCirculars()
+ val newCirculars = fetcher.getCircularsFromServer()
+
+ if (newCirculars.size != oldCirculars.size) {
+ for (i in oldCirculars.lastIndex..newCirculars.lastIndex) {
+ createNotificationChannel()
+ createNotification(newCirculars[i])
+ }
+
+ AppDatabase.getInstance(applicationContext).circularDao().deleteAll()
+ AppDatabase.getInstance(applicationContext).circularDao().insertAll(newCirculars)
+ }
+ return Result.success()
+ }
+
+ private fun createNotification(circular: Circular) {
+ val intent = Intent(applicationContext, MainActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ }
+ val pendingIntent: PendingIntent =
+ PendingIntent.getActivity(applicationContext, 0, intent, 0)
+
+ val builder = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_notifications_black_24dp)
+ .setContentTitle(applicationContext.getString(R.string.notification_title, circular.id))
+ .setContentText(circular.name)
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setContentIntent(pendingIntent)
+ .setGroup(CHANNEL_ID)
+ .setStyle(
+ NotificationCompat.BigTextStyle()
+ .bigText(circular.name)
+ )
+
+ with(NotificationManagerCompat.from(applicationContext)) {
+ notify(circular.id.toInt(), builder.build())
+ }
+ }
+
+ private fun createNotificationChannel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = applicationContext.getString(R.string.channel_name)
+ val descriptionText = applicationContext.getString(R.string.channel_description)
+ val importance = NotificationManager.IMPORTANCE_DEFAULT
+ val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
+ description = descriptionText
+ }
+
+ val notificationManager: NotificationManager =
+ applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(channel)
+ }
+ }
+
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2198455..baba40b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,4 +3,9 @@
Circular letters
Favourites
Reminders
+
+ Published circular letter number %1$d
+
+ Circular letters
+ Notify when your school issue a new circular letter