From ae53e941089d08f550656bc71aec070716d31f8c Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Mon, 7 Jan 2019 14:59:48 +0100 Subject: [PATCH] Periodic sync, reload from memory if outdated --- .../java/de/sebse/fuplanner/MainActivity.java | 11 +++- .../services/fulogin/AccountGeneral.java | 1 + .../fuplanner/services/kvv/ModulesList.java | 18 +++++-- .../services/kvv/sync/KVVContentProvider.java | 2 +- .../fuplanner/services/kvv/types/Modules.java | 51 ++++++++++++++++++- .../fuplanner/tools/CustomAccountManager.java | 7 +++ 6 files changed, 83 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 0cd5b87..17bbbc1 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -1,6 +1,7 @@ package de.sebse.fuplanner; import android.accounts.AccountManager; +import android.content.ContentResolver; import android.content.Intent; import android.os.Bundle; import android.view.Menu; @@ -39,12 +40,13 @@ import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment; import de.sebse.fuplanner.services.canteen.CanteenBrowser; import de.sebse.fuplanner.services.canteen.types.Canteen; import de.sebse.fuplanner.services.canteen.types.CanteenListener; +import de.sebse.fuplanner.services.fulogin.AccountGeneral; import de.sebse.fuplanner.services.kvv.KVV; import de.sebse.fuplanner.services.kvv.KVVListener; +import de.sebse.fuplanner.services.kvv.sync.KVVContentProvider; import de.sebse.fuplanner.services.kvv.types.LoginToken; import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.services.news.NewsManager; -import de.sebse.fuplanner.services.fulogin.AccountGeneral; import de.sebse.fuplanner.tools.CustomAccountManager; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.NewAsyncQueue; @@ -136,6 +138,12 @@ public class MainActivity extends AppCompatActivity changeFragment(getDefaultFragmentAfterLogout()); }); } + ContentResolver.addPeriodicSync( + mAccountManager.getAccountByType(AccountGeneral.ACCOUNT_TYPE), + KVVContentProvider.PROVIDER_NAME, + Bundle.EMPTY, + AccountGeneral.SYNC_INTERVAL); + } @Override @@ -158,6 +166,7 @@ public class MainActivity extends AppCompatActivity changeFragment(getDefaultFragmentAfterLogout()); } }); + getKVV().modules().list().reloadIfOutdated(); } isPaused = false; } diff --git a/app/src/main/java/de/sebse/fuplanner/services/fulogin/AccountGeneral.java b/app/src/main/java/de/sebse/fuplanner/services/fulogin/AccountGeneral.java index 7c15881..af6749e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/fulogin/AccountGeneral.java +++ b/app/src/main/java/de/sebse/fuplanner/services/fulogin/AccountGeneral.java @@ -4,4 +4,5 @@ public class AccountGeneral { public static final String ACCOUNT_TYPE = "de.sebse.fuplanner.fuauth"; public static final String AUTHTOKEN_TYPE_KVV = "KVV"; public static final String AUTHTOKEN_TYPE_BLACKBOARD = "Blackboard"; + public static final long SYNC_INTERVAL = 6 * 60 * 60; // defined in seconds } diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java index b21635a..2707c52 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java @@ -46,6 +46,16 @@ public class ModulesList extends HTTPService { return null; } + public void reloadIfOutdated() { + try { + if (mModules != null && mModules.isNewerVersionInStorage(getContext())) { + restore(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + public void find(String moduleID, NetworkCallback moduleNetworkCallback, NetworkErrorCallback errorCallback) { find(moduleID, moduleNetworkCallback, errorCallback, RETRY_COUNT); } @@ -115,10 +125,10 @@ public class ModulesList extends HTTPService { this.upgrade(success -> { if (this.mModules == null) this.mModules = success; - else - this.mModules.updateList(success); - mListener.onModuleListChange(); - store(); + else if(this.mModules.updateList(success)) { + mListener.onModuleListChange(); + store(); + } callback.onResponse(this.mModules); mQueue.next(); }, error -> { diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVContentProvider.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVContentProvider.java index 2ea6c78..ec78580 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVContentProvider.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/sync/KVVContentProvider.java @@ -11,7 +11,7 @@ import androidx.annotation.Nullable; public class KVVContentProvider extends ContentProvider { - private static final String PROVIDER_NAME = "de.sebse.fuplanner.contentprovider.kvv.modules"; + public static final String PROVIDER_NAME = "de.sebse.fuplanner.contentprovider.kvv.modules"; private static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/modules"); private static final int MODULE = 1; private static final int MODULE_ID = 2; diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Modules.java index 8ca426b..128ba8e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/Modules.java @@ -2,6 +2,8 @@ package de.sebse.fuplanner.services.kvv.types; import android.content.Context; +import com.google.android.gms.common.internal.Objects; + import org.jetbrains.annotations.NotNull; import java.io.FileInputStream; @@ -25,8 +27,10 @@ import androidx.annotation.Nullable; public class Modules implements Iterable, Serializable { private SortedListModule list; private final String mUsername; + private transient long mLastTimestamp = 0; //private transient Logger log = new Logger(this); private static final String FILE_NAME = "ModuleListSaving"; + private static final String FILE_NAME_TIMESTAMP = "ModuleListSavingTimestamp"; public Modules(String username) { this.mUsername = username; @@ -75,15 +79,38 @@ public class Modules implements Iterable, Serializable { Modules modules = (Modules) readObject; is.close(); fis.close(); + + fis = context.openFileInput(FILE_NAME_TIMESTAMP); + is = new ObjectInputStream(fis); + modules.mLastTimestamp = is.readLong(); + is.close(); + fis.close(); + return modules; } + public boolean isNewerVersionInStorage(Context context) throws IOException { + FileInputStream fis = context.openFileInput(FILE_NAME_TIMESTAMP); + ObjectInputStream is = new ObjectInputStream(fis); + boolean result = this.mLastTimestamp < is.readLong(); + is.close(); + fis.close(); + return result; + } + public void save(Context context) throws IOException { FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(this); os.close(); fos.close(); + + fos = context.openFileOutput(FILE_NAME_TIMESTAMP, Context.MODE_PRIVATE); + os = new ObjectOutputStream(fos); + this.mLastTimestamp = System.currentTimeMillis(); + os.writeLong(this.mLastTimestamp); + os.close(); + fos.close(); } public void delete(Context context) { @@ -94,19 +121,36 @@ public class Modules implements Iterable, Serializable { return mUsername; } - public void updateList(Modules modules) { + public boolean updateList(Modules modules) { SortedListModule old = this.list; this.list = modules.list; + boolean isChanged = false; for (Module oldModule : old) { Module newModule = this.list.getById(oldModule.getID()); if (newModule != null) { + if (!isChanged && !hashEquals(oldModule, newModule)) + isChanged = true; newModule.announcements = oldModule.announcements; newModule.assignments = oldModule.assignments; newModule.events = oldModule.events; newModule.gradebook = oldModule.gradebook; newModule.resources = oldModule.resources; + } else { + isChanged = true; } } + if (this.list.size() != old.size()) + isChanged = true; + return isChanged; + } + + private boolean hashEquals(Module o1, Module o2) { + if (o1 == null && o2 == null) + return true; + else if (o1 == null || o2 == null) + return false; + else + return o1.hashCode() == o2.hashCode(); } public class Module implements Serializable { @@ -166,5 +210,10 @@ public class Modules implements Iterable, Serializable { "\ntype: "+type+ "\nID: "+ID; } + + @Override + public int hashCode() { + return Objects.hashCode(semester, lvNumber, title, lecturer, type, description, ID); + } } } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java index 782f637..82b0643 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/CustomAccountManager.java @@ -122,6 +122,13 @@ public class CustomAccountManager { return mAccountManager.getAccountsByType(accountType).length != 0; } + public Account getAccountByType(String accountType) { + Account[] accountsByType = mAccountManager.getAccountsByType(accountType); + if (accountsByType.length > 0) + return accountsByType[0]; + return null; + } + @FunctionalInterface public interface ActivityInterface { @Nullable