From 257bb949313aaca19c954100c90e185631996fe8 Mon Sep 17 00:00:00 2001
From: Prateek Singh <76490368+prateek-singh-3212@users.noreply.github.com>
Date: Tue, 31 May 2022 23:46:17 +0530
Subject: [PATCH] Implemented Base for fetching Deck Meta Data
---
AnkiDroid/build.gradle | 3 +
AnkiDroid/src/main/AndroidManifest.xml | 5 +
.../com/ichi2/anki/DeckMetaDataPreference.kt | 42 ++++++
.../main/java/com/ichi2/anki/IntentHandler.kt | 12 ++
.../anki/services/DeckMetaDataService.kt | 127 ++++++++++++++++++
5 files changed, 189 insertions(+)
create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/DeckMetaDataPreference.kt
create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/services/DeckMetaDataService.kt
diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle
index 8e81a4c290e1..0e670e535f44 100644
--- a/AnkiDroid/build.gradle
+++ b/AnkiDroid/build.gradle
@@ -328,5 +328,8 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test:rules:1.4.0'
+
+ // GSON
+ implementation 'com.google.code.gson:gson:2.9.0'
}
apply from: "./kotlinMigration.gradle"
diff --git a/AnkiDroid/src/main/AndroidManifest.xml b/AnkiDroid/src/main/AndroidManifest.xml
index b9a802893408..62377325650b 100644
--- a/AnkiDroid/src/main/AndroidManifest.xml
+++ b/AnkiDroid/src/main/AndroidManifest.xml
@@ -377,6 +377,11 @@
+
+
= Build.VERSION_CODES.O) {
+ startForegroundService(intent)
+ } else {
+ startService(intent)
+ }
+ }
+
// COULD_BE_BETTER: Also extract the parameters into here to reduce coupling
@VisibleForTesting
enum class LaunchType {
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/services/DeckMetaDataService.kt b/AnkiDroid/src/main/java/com/ichi2/anki/services/DeckMetaDataService.kt
new file mode 100644
index 000000000000..fe8a67dc449d
--- /dev/null
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/services/DeckMetaDataService.kt
@@ -0,0 +1,127 @@
+package com.ichi2.anki.services
+
+import android.annotation.SuppressLint
+import android.app.AlarmManager
+import android.app.Notification
+import android.app.PendingIntent
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationCompat.*
+import com.ichi2.anki.CollectionHelper
+import com.ichi2.anki.DeckMetaDataPreference
+import com.ichi2.anki.NotificationChannels
+import com.ichi2.anki.R
+import com.ichi2.libanki.sched.Counts
+import com.ichi2.libanki.utils.Time
+import timber.log.Timber
+import java.util.*
+
+class DeckMetaDataService : Service() {
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+
+ Timber.tag("META").e("On Service start command...")
+
+ /**
+ * It sets the notification till the service is completed.
+ * */
+ val notification = NotificationCompat.Builder(this, NotificationChannels.getId(NotificationChannels.Channel.GENERAL))
+ .setOngoing(true)
+ .setContentTitle("Anki")
+ .setContentText("Ankidroid is syncing deck data.")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setPriority(PRIORITY_LOW)
+ .setSilent(true)
+ .setCategory(Notification.CATEGORY_SERVICE)
+ .build()
+
+ startForeground(FOREGROUND_SERVICE_ID, notification)
+
+ // Update the data of Deck Metadata from HERE
+ val col = CollectionHelper.getInstance().getCol(this)
+ val deckList = col.sched.deckDueList()
+
+ deckList.forEach {
+ val new = it?.newCount ?: -1
+ val lrn = it?.lrnCount ?: -1
+ val rev = it?.revCount ?: -1
+ val data = Meta(
+ it?.did ?: -1,
+ it?.fullDeckName ?: "Deck Name",
+ new,
+ lrn,
+ rev,
+ col.sched.eta(Counts(new, lrn, rev), false)
+ )
+ storeInPreference(data)
+ }
+
+ updateLastFetch()
+
+ stopSelf() // Stops the current running service.
+ return START_NOT_STICKY
+ }
+
+ private fun updateLastFetch() {
+ val metaPreference = DeckMetaDataPreference(this)
+ metaPreference.setString(LAST_FETCH_TIME, System.currentTimeMillis().toString())
+ }
+
+ /**
+ * It is used to store the data in the DeckMetaData Shared Preference.
+ * */
+ private fun storeInPreference(list: Meta) {
+ val metaPreference = DeckMetaDataPreference(this)
+ metaPreference.setMetaData(list.did.toString(), list)
+ }
+
+ /**
+ * Does Nothing
+ * */
+ override fun onBind(intent: Intent?): IBinder? {
+ // Kept Intentionally
+ return null
+ }
+
+ override fun onDestroy() {
+ Timber.tag("META").e("Deck meta data Service on Destroy...")
+ scheduleNextAlarm(Long.MAX_VALUE) // Temp
+ }
+
+ /**
+ * It is used to schedule the next alarm which helps in starting this service again.
+ **/
+ @SuppressLint("UnspecifiedImmutableFlag")
+ private fun scheduleNextAlarm(interval: Long) {
+
+ val intent = Intent(this, DeckMetaDataService::class.java)
+ val pendingIntent = PendingIntent.getService(
+ this.applicationContext, SERVICE_PENDING_INTENT_ID, intent, 0
+ )
+
+ val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
+ alarmManager.set(
+ AlarmManager.RTC_WAKEUP,
+ System.currentTimeMillis() + interval,
+ pendingIntent
+ )
+ Timber.tag("META").e("Service will start again at %s", (Time.calendar(System.currentTimeMillis() + interval).time))
+ }
+
+ data class Meta(
+ val did: Long,
+ val deckName: String,
+ val new: Int,
+ val lrn: Int,
+ val rev: Int,
+ val eta: Int
+ )
+
+ companion object {
+ const val FOREGROUND_SERVICE_ID = 10001
+ const val SERVICE_PENDING_INTENT_ID = 10002
+ const val LAST_FETCH_TIME = "LAST_FETCH"
+ }
+}