diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index d22c131cb026..2116177bdc9e 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -329,9 +329,6 @@ dependencies { 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' - // Work Manager implementation "androidx.work:work-runtime-ktx:2.7.1" } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.java b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.java index a36719d2caeb..6b580ea8f2a3 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.java +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.java @@ -428,7 +428,7 @@ public static String getWebViewErrorMessage() { private void setupDeckMetaDataWorker() { Timber.tag("META").e("Setting up deck meta data worker..."); - PeriodicWorkRequest deckMetaDataWorker = new PeriodicWorkRequest.Builder(DeckMetaDataWorker.class, 2, TimeUnit.MINUTES) + PeriodicWorkRequest deckMetaDataWorker = new PeriodicWorkRequest.Builder(DeckMetaDataWorker.class, 30, TimeUnit.MINUTES) .addTag(DeckMetaDataWorker.DECK_META_WORKER) .build(); @@ -438,6 +438,9 @@ private void setupDeckMetaDataWorker() { ExistingPeriodicWorkPolicy.REPLACE, deckMetaDataWorker ); + + // Does the required work in setting up new Worker. + DeckMetaDataWorker.Companion.setupNewWorker(this); } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckMetaDataPreference.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckMetaDataPreference.kt index b10cea04c7b5..9322a5913782 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckMetaDataPreference.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckMetaDataPreference.kt @@ -18,8 +18,10 @@ package com.ichi2.anki import android.content.Context import android.content.SharedPreferences -import com.google.gson.Gson +import androidx.core.content.edit import com.ichi2.anki.worker.DeckMetaDataWorker +import com.ichi2.utils.JSONException +import com.ichi2.utils.JSONObject import timber.log.Timber class DeckMetaDataPreference(context: Context) { @@ -27,24 +29,82 @@ class DeckMetaDataPreference(context: Context) { private val sharedPreferences: SharedPreferences = context.getSharedPreferences("DeckMetaData", Context.MODE_PRIVATE) + /** + * Use this to store data in shared preference. + * @param key The Key of value. Used in fetching the data. + * @param value Value that needs to be stored (VALUE MUST BE STRING). + * */ fun putString(key: String, value: String) { - sharedPreferences.edit() - .putString(key, value) - .apply() + sharedPreferences.edit { + putString(key, value) + apply() + } } + /** + * Use this to fetch string from shared preference. + * @prams The Key of deck whose data you want to fetch. + * @return Value that needs to be fetched (VALUE WILL BE STRING). + * */ fun getString(key: String, default: String): String { return sharedPreferences.getString(key, default)!! } + /** + * Use this to store int in shared preference. + * @param key The Key of value. Created while storing the data. + * @param value Value that needs to be stored (VALUE MUST BE INTEGER). + * */ + fun putInt(key: String, value: Int) { + sharedPreferences.edit { + putInt(key, value) + apply() + } + } + + /** + * Use this to fetch integer from shared preference. + * @prams The Key of deck whose data you want to fetch. + * @return Value that needs to be fetched (VALUE WILL BE INTEGER). + * */ + fun getInt(key: String, default: Int): Int { + return sharedPreferences.getInt(key, default) + } + + /** + * Use this to store meta data in shared preference. + * @param key The Key of deck whose data you want to fetch. (deck id is the for deck) + * @param value Object of Metadata Model + * */ fun setMetaData(key: String, value: DeckMetaDataWorker.Meta) { - val json: String = Gson().toJson(value) - sharedPreferences.edit() - .putString(key, json) - .apply() + val jsonObject = JSONObject() + + try { + jsonObject.put("did", value.did) + jsonObject.put("deckName", value.deckName) + jsonObject.put("new", value.new) + jsonObject.put("lrn", value.lrn) + jsonObject.put("rev", value.rev) + jsonObject.put("eta", value.eta) + } catch (e: JSONException) { + Timber.tag("META").e(e) + return + } + + val json = jsonObject.toString() + + sharedPreferences.edit { + putString(key, json) + apply() + } Timber.tag("META").e(json) } + /** + * Use this to fetch meta data from shared preference if Deck ID (did) is known. + * @prams The Key of deck whose data you want to fetch. (deck id is the for deck) + * @return Object of Metadata Model. + * */ fun getMetaData(key: String): DeckMetaDataWorker.Meta? { val jsonData = sharedPreferences .getString(key, null) @@ -52,7 +112,15 @@ class DeckMetaDataPreference(context: Context) { return if (jsonData == null) { null } else { - Gson().fromJson(jsonData, DeckMetaDataWorker.Meta::class.java) + val jsonObject = JSONObject(jsonData) + return DeckMetaDataWorker.Meta( + jsonObject.getLong("did"), + jsonObject.getString("deckName"), + jsonObject.getInt("new"), + jsonObject.getInt("lrn"), + jsonObject.getInt("rev"), + jsonObject.getInt("eta"), + ) } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/worker/DeckMetaDataWorker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/worker/DeckMetaDataWorker.kt index fb4a53bca815..9e3d24952cdd 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/worker/DeckMetaDataWorker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/worker/DeckMetaDataWorker.kt @@ -21,7 +21,9 @@ import androidx.work.Worker import androidx.work.WorkerParameters import com.ichi2.anki.CollectionHelper import com.ichi2.anki.DeckMetaDataPreference +import com.ichi2.libanki.Collection import com.ichi2.libanki.sched.Counts +import com.ichi2.libanki.sched.DeckDueTreeNode import timber.log.Timber /** @@ -31,18 +33,27 @@ import timber.log.Timber * */ class DeckMetaDataWorker(val context: Context, workerParameters: WorkerParameters) : Worker(context, workerParameters) { - private lateinit var colHelper: CollectionHelper + // Lambda to check the collection is not null. + private val mCollection: (context: Context) -> Collection? = { + val collection = CollectionHelper.getInstance() + if (collection.getColSafe(it) != null) { + collection.getCol(it) + } else { + null + } + } override fun doWork(): Result { - colHelper = CollectionHelper.getInstance() + val date = CollectionHelper.getInstance().getTimeSafe(context).currentDate - Timber.tag("META").e("Deck Meta Data Worker started at: ${colHelper.getTimeSafe(context).currentDate}") + Timber.tag("META").e("Deck Meta Data Worker started at: $date") // Update the data of Deck Metadata from HERE - val col = colHelper.getCol(context) - val deckList = col.sched.deckDueList() + val deckList: List = + mCollection(context)?.sched?.deckDueList() ?: return Result.failure() + val sched = mCollection(context)?.sched ?: return Result.failure() deckList.forEach { val new = it?.newCount ?: -1 val lrn = it?.lrnCount ?: -1 @@ -53,12 +64,12 @@ class DeckMetaDataWorker(val context: Context, workerParameters: WorkerParameter new, lrn, rev, - col.sched.eta(Counts(new, lrn, rev), false) + sched.eta(Counts(new, lrn, rev), false) ) storeInPreference(data) } - updateLastFetch(colHelper.getTimeSafe(context).toString()) + updateLastFetch(date.toString()) return Result.success() // Done work successfully... } @@ -66,6 +77,8 @@ class DeckMetaDataWorker(val context: Context, workerParameters: WorkerParameter private fun updateLastFetch(time: String) { val metaPreference = DeckMetaDataPreference(context) metaPreference.putString(LAST_FETCH_TIME, time) + val prevData = metaPreference.getInt(TIMES_FETCHED, 0) + metaPreference.putInt(TIMES_FETCHED, prevData + 1) } /** @@ -74,6 +87,8 @@ class DeckMetaDataWorker(val context: Context, workerParameters: WorkerParameter private fun storeInPreference(list: Meta) { val metaPreference = DeckMetaDataPreference(context) metaPreference.setMetaData(list.did.toString(), list) + val data = metaPreference.getMetaData(list.did.toString()) + data.toString() } data class Meta( @@ -88,5 +103,17 @@ class DeckMetaDataWorker(val context: Context, workerParameters: WorkerParameter companion object { const val DECK_META_WORKER = "DeckMetaData" const val LAST_FETCH_TIME = "LAST_FETCH" + const val TIMES_FETCHED = "TIMES_FETCHED" + const val WORKER_CREATED = "WORKER_CREATED" + + fun setupNewWorker(context: Context) { + Timber.tag("META").e("Setting up Preference for new Worker.") + + val time = CollectionHelper.getInstance().getTimeSafe(context) + + val metaDataPreference = DeckMetaDataPreference(context) + metaDataPreference.putString(WORKER_CREATED, time.currentDate.toString()) + metaDataPreference.putInt(TIMES_FETCHED, 0) + } } }