Periodic sync, reload from memory if outdated
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package de.sebse.fuplanner;
|
package de.sebse.fuplanner;
|
||||||
|
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
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.CanteenBrowser;
|
||||||
import de.sebse.fuplanner.services.canteen.types.Canteen;
|
import de.sebse.fuplanner.services.canteen.types.Canteen;
|
||||||
import de.sebse.fuplanner.services.canteen.types.CanteenListener;
|
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.KVV;
|
||||||
import de.sebse.fuplanner.services.kvv.KVVListener;
|
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.LoginToken;
|
||||||
import de.sebse.fuplanner.services.kvv.types.Modules;
|
import de.sebse.fuplanner.services.kvv.types.Modules;
|
||||||
import de.sebse.fuplanner.services.news.NewsManager;
|
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.CustomAccountManager;
|
||||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||||
import de.sebse.fuplanner.tools.NewAsyncQueue;
|
import de.sebse.fuplanner.tools.NewAsyncQueue;
|
||||||
@@ -136,6 +138,12 @@ public class MainActivity extends AppCompatActivity
|
|||||||
changeFragment(getDefaultFragmentAfterLogout());
|
changeFragment(getDefaultFragmentAfterLogout());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
ContentResolver.addPeriodicSync(
|
||||||
|
mAccountManager.getAccountByType(AccountGeneral.ACCOUNT_TYPE),
|
||||||
|
KVVContentProvider.PROVIDER_NAME,
|
||||||
|
Bundle.EMPTY,
|
||||||
|
AccountGeneral.SYNC_INTERVAL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -158,6 +166,7 @@ public class MainActivity extends AppCompatActivity
|
|||||||
changeFragment(getDefaultFragmentAfterLogout());
|
changeFragment(getDefaultFragmentAfterLogout());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
getKVV().modules().list().reloadIfOutdated();
|
||||||
}
|
}
|
||||||
isPaused = false;
|
isPaused = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ public class AccountGeneral {
|
|||||||
public static final String ACCOUNT_TYPE = "de.sebse.fuplanner.fuauth";
|
public static final String ACCOUNT_TYPE = "de.sebse.fuplanner.fuauth";
|
||||||
public static final String AUTHTOKEN_TYPE_KVV = "KVV";
|
public static final String AUTHTOKEN_TYPE_KVV = "KVV";
|
||||||
public static final String AUTHTOKEN_TYPE_BLACKBOARD = "Blackboard";
|
public static final String AUTHTOKEN_TYPE_BLACKBOARD = "Blackboard";
|
||||||
|
public static final long SYNC_INTERVAL = 6 * 60 * 60; // defined in seconds
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,16 @@ public class ModulesList extends HTTPService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reloadIfOutdated() {
|
||||||
|
try {
|
||||||
|
if (mModules != null && mModules.isNewerVersionInStorage(getContext())) {
|
||||||
|
restore();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void find(String moduleID, NetworkCallback<Modules.Module> moduleNetworkCallback, NetworkErrorCallback errorCallback) {
|
public void find(String moduleID, NetworkCallback<Modules.Module> moduleNetworkCallback, NetworkErrorCallback errorCallback) {
|
||||||
find(moduleID, moduleNetworkCallback, errorCallback, RETRY_COUNT);
|
find(moduleID, moduleNetworkCallback, errorCallback, RETRY_COUNT);
|
||||||
}
|
}
|
||||||
@@ -115,10 +125,10 @@ public class ModulesList extends HTTPService {
|
|||||||
this.upgrade(success -> {
|
this.upgrade(success -> {
|
||||||
if (this.mModules == null)
|
if (this.mModules == null)
|
||||||
this.mModules = success;
|
this.mModules = success;
|
||||||
else
|
else if(this.mModules.updateList(success)) {
|
||||||
this.mModules.updateList(success);
|
mListener.onModuleListChange();
|
||||||
mListener.onModuleListChange();
|
store();
|
||||||
store();
|
}
|
||||||
callback.onResponse(this.mModules);
|
callback.onResponse(this.mModules);
|
||||||
mQueue.next();
|
mQueue.next();
|
||||||
}, error -> {
|
}, error -> {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import androidx.annotation.Nullable;
|
|||||||
|
|
||||||
public class KVVContentProvider extends ContentProvider {
|
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 Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/modules");
|
||||||
private static final int MODULE = 1;
|
private static final int MODULE = 1;
|
||||||
private static final int MODULE_ID = 2;
|
private static final int MODULE_ID = 2;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package de.sebse.fuplanner.services.kvv.types;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.google.android.gms.common.internal.Objects;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@@ -25,8 +27,10 @@ import androidx.annotation.Nullable;
|
|||||||
public class Modules implements Iterable<Modules.Module>, Serializable {
|
public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||||
private SortedListModule list;
|
private SortedListModule list;
|
||||||
private final String mUsername;
|
private final String mUsername;
|
||||||
|
private transient long mLastTimestamp = 0;
|
||||||
//private transient Logger log = new Logger(this);
|
//private transient Logger log = new Logger(this);
|
||||||
private static final String FILE_NAME = "ModuleListSaving";
|
private static final String FILE_NAME = "ModuleListSaving";
|
||||||
|
private static final String FILE_NAME_TIMESTAMP = "ModuleListSavingTimestamp";
|
||||||
|
|
||||||
public Modules(String username) {
|
public Modules(String username) {
|
||||||
this.mUsername = username;
|
this.mUsername = username;
|
||||||
@@ -75,15 +79,38 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
|||||||
Modules modules = (Modules) readObject;
|
Modules modules = (Modules) readObject;
|
||||||
is.close();
|
is.close();
|
||||||
fis.close();
|
fis.close();
|
||||||
|
|
||||||
|
fis = context.openFileInput(FILE_NAME_TIMESTAMP);
|
||||||
|
is = new ObjectInputStream(fis);
|
||||||
|
modules.mLastTimestamp = is.readLong();
|
||||||
|
is.close();
|
||||||
|
fis.close();
|
||||||
|
|
||||||
return modules;
|
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 {
|
public void save(Context context) throws IOException {
|
||||||
FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
|
FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
|
||||||
ObjectOutputStream os = new ObjectOutputStream(fos);
|
ObjectOutputStream os = new ObjectOutputStream(fos);
|
||||||
os.writeObject(this);
|
os.writeObject(this);
|
||||||
os.close();
|
os.close();
|
||||||
fos.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) {
|
public void delete(Context context) {
|
||||||
@@ -94,19 +121,36 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
|||||||
return mUsername;
|
return mUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateList(Modules modules) {
|
public boolean updateList(Modules modules) {
|
||||||
SortedListModule old = this.list;
|
SortedListModule old = this.list;
|
||||||
this.list = modules.list;
|
this.list = modules.list;
|
||||||
|
boolean isChanged = false;
|
||||||
for (Module oldModule : old) {
|
for (Module oldModule : old) {
|
||||||
Module newModule = this.list.getById(oldModule.getID());
|
Module newModule = this.list.getById(oldModule.getID());
|
||||||
if (newModule != null) {
|
if (newModule != null) {
|
||||||
|
if (!isChanged && !hashEquals(oldModule, newModule))
|
||||||
|
isChanged = true;
|
||||||
newModule.announcements = oldModule.announcements;
|
newModule.announcements = oldModule.announcements;
|
||||||
newModule.assignments = oldModule.assignments;
|
newModule.assignments = oldModule.assignments;
|
||||||
newModule.events = oldModule.events;
|
newModule.events = oldModule.events;
|
||||||
newModule.gradebook = oldModule.gradebook;
|
newModule.gradebook = oldModule.gradebook;
|
||||||
newModule.resources = oldModule.resources;
|
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 {
|
public class Module implements Serializable {
|
||||||
@@ -166,5 +210,10 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
|||||||
"\ntype: "+type+
|
"\ntype: "+type+
|
||||||
"\nID: "+ID;
|
"\nID: "+ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(semester, lvNumber, title, lecturer, type, description, ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,13 @@ public class CustomAccountManager {
|
|||||||
return mAccountManager.getAccountsByType(accountType).length != 0;
|
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
|
@FunctionalInterface
|
||||||
public interface ActivityInterface {
|
public interface ActivityInterface {
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
Reference in New Issue
Block a user