/**
* Copyright (C) 2013 by Raphael Michel under the MIT license:
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package de.geeksfactory.opacclient.reminder;
import android.app.AlarmManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.preference.PreferenceManager;
import android.util.Log;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import org.acra.ACRA;
import org.joda.time.DateTime;
import org.joda.time.Hours;
import org.json.JSONException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import de.geeksfactory.opacclient.BuildConfig;
import de.geeksfactory.opacclient.OpacClient;
import de.geeksfactory.opacclient.apis.OpacApi;
import de.geeksfactory.opacclient.objects.Account;
import de.geeksfactory.opacclient.objects.AccountData;
import de.geeksfactory.opacclient.objects.Library;
import de.geeksfactory.opacclient.storage.AccountDataSource;
import de.geeksfactory.opacclient.storage.JsonSearchFieldDataSource;
import de.geeksfactory.opacclient.storage.PreferenceDataSource;
import de.geeksfactory.opacclient.webservice.LibraryConfigUpdateService;
import de.geeksfactory.opacclient.webservice.WebService;
import de.geeksfactory.opacclient.webservice.WebServiceManager;
public class SyncAccountService extends WakefulIntentService {
private static final String NAME = "SyncAccountService";
public SyncAccountService() {
super(NAME);
}
@Override
protected void doWakefulWork(Intent intent) {
if (BuildConfig.DEBUG) Log.i(NAME, "SyncAccountService started");
updateLibraryConfig();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (!sp.getBoolean(SyncAccountAlarmListener.PREF_SYNC_SERVICE, false)) {
if (BuildConfig.DEBUG) Log.i(NAME, "notifications are disabled");
return;
}
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
boolean failed;
if (networkInfo != null) {
if (!sp.getBoolean("notification_service_wifionly", false) ||
networkInfo.getType() == ConnectivityManager.TYPE_WIFI ||
networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
OpacClient app = (OpacClient) getApplication();
AccountDataSource data = new AccountDataSource(this);
ReminderHelper helper = new ReminderHelper(app);
failed = syncAccounts(app, data, sp, helper);
} else {
failed = true;
}
} else {
failed = true;
}
if (BuildConfig.DEBUG) {
Log.i(NAME, "SyncAccountService finished " +
(failed ? " with errors" : " " + "successfully"));
}
long previousPeriod = sp.getLong(SyncAccountAlarmListener.PREF_SYNC_INTERVAL, 0);
long newPeriod = failed ? AlarmManager.INTERVAL_HOUR : AlarmManager.INTERVAL_HALF_DAY;
if (previousPeriod != newPeriod) {
sp.edit().putLong(SyncAccountAlarmListener.PREF_SYNC_INTERVAL, newPeriod).apply();
WakefulIntentService.cancelAlarms(this);
WakefulIntentService
.scheduleAlarms(SyncAccountAlarmListener.withOnePeriodBeforeStart(), this);
}
}
private void updateLibraryConfig() {
PreferenceDataSource prefs = new PreferenceDataSource(this);
if (prefs.getLastLibraryConfigUpdate() != null
&& prefs.getLastLibraryConfigUpdate()
.isAfter(DateTime.now().minus(Hours.ONE))) {
Log.d(NAME, "Do not run updateLibraryConfig as last run was less than an hour ago.");
return;
}
WebService service = WebServiceManager.getInstance();
File filesDir = new File(getFilesDir(), LibraryConfigUpdateService.LIBRARIES_DIR);
filesDir.mkdirs();
try {
int count = ((OpacClient) getApplication()).getUpdateHandler().updateConfig(
service, prefs,
new LibraryConfigUpdateService.FileOutput(filesDir),
new JsonSearchFieldDataSource(this));
Log.d(NAME, "updated config for " + String.valueOf(count) + " libraries");
((OpacClient) getApplication()).resetCache();
if (!BuildConfig.DEBUG) {
ACRA.getErrorReporter().putCustomData("data_version",
prefs.getLastLibraryConfigUpdate().toString());
}
} catch (IOException | JSONException ignore) {
}
}
boolean syncAccounts(OpacClient app, AccountDataSource data, SharedPreferences sp,
ReminderHelper helper) {
boolean failed = false;
List<Account> accounts = data.getAccountsWithPassword();
if (!sp.contains("update_151_clear_cache")) {
data.invalidateCachedData();
sp.edit().putBoolean("update_151_clear_cache", true).apply();
}
for (Account account : accounts) {
if (BuildConfig.DEBUG)
Log.i(NAME, "Loading data for Account " + account.toString());
AccountData res;
try {
Library library = app.getLibrary(account.getLibrary());
if (!library.isAccountSupported()) {
data.deleteAccountData(account);
continue;
}
OpacApi api = app.getNewApi(library);
res = api.account(account);
if (res == null) {
failed = true;
continue;
}
} catch (JSONException | IOException | OpacApi.OpacErrorException e) {
e.printStackTrace();
failed = true;
continue;
} catch (OpacClient.LibraryRemovedException e) {
continue;
}
account.setPasswordKnownValid(true);
try {
data.update(account);
data.storeCachedAccountData(account, res);
} finally {
helper.generateAlarms();
}
}
return failed;
}
}