1
0
mirror of https://github.com/etesync/android synced 2024-11-22 16:08:13 +00:00

New feature: only sync in WiFi

* new setting: only sync in WiFi (or when sync is triggered manually)
* new setting: only sync in specific WiFI (by SSID)
* lower default sync interval when account is created to 4 hours (was 1 day)
* version bump to 1.0.6
This commit is contained in:
Ricki Hirner 2016-04-06 21:04:16 +02:00
parent 03ee9a037b
commit 6ffa6fa9a7
17 changed files with 179 additions and 99 deletions

View File

@ -17,8 +17,8 @@ android {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 22 targetSdkVersion 22
versionCode 95 versionCode 96
versionName "1.0.5" versionName "1.0.6"
buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" buildConfigField "long", "buildTime", System.currentTimeMillis() + "L"
} }

View File

@ -12,6 +12,8 @@
android:installLocation="internalOnly"> android:installLocation="internalOnly">
<!-- normal permissions --> <!-- normal permissions -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>

View File

@ -24,6 +24,7 @@ import android.os.Bundle;
import android.provider.CalendarContract; import android.provider.CalendarContract;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.NotificationCompat; import android.support.v7.app.NotificationCompat;
import android.text.TextUtils; import android.text.TextUtils;
@ -49,10 +50,13 @@ import okhttp3.HttpUrl;
public class AccountSettings { public class AccountSettings {
private final static int CURRENT_VERSION = 3; private final static int CURRENT_VERSION = 3;
private final static String private final static String
KEY_SETTINGS_VERSION = "version", KEY_SETTINGS_VERSION = "version",
KEY_USERNAME = "user_name", KEY_USERNAME = "user_name",
KEY_AUTH_PREEMPTIVE = "auth_preemptive"; KEY_AUTH_PREEMPTIVE = "auth_preemptive",
KEY_WIFI_ONLY = "wifi_only", // sync on WiFi only (default: false)
KEY_WIFI_ONLY_SSID = "wifi_only_ssid"; // restrict sync to specific WiFi SSID
/** Time range limitation to the past [in days] /** Time range limitation to the past [in days]
value = null default value (DEFAULT_TIME_RANGE_PAST_DAYS) value = null default value (DEFAULT_TIME_RANGE_PAST_DAYS)
@ -159,6 +163,26 @@ public class AccountSettings {
} }
} }
public boolean getSyncWifiOnly() {
return accountManager.getUserData(account, KEY_WIFI_ONLY) != null;
}
public void setSyncWiFiOnly(boolean wiFiOnly) {
accountManager.setUserData(account, KEY_WIFI_ONLY, wiFiOnly ? "1" : null);
}
@Nullable
public String getSyncWifiOnlySSID() {
return accountManager.getUserData(account, KEY_WIFI_ONLY_SSID);
}
public void setSyncWifiOnlySSID(String ssid) {
accountManager.setUserData(account, KEY_WIFI_ONLY_SSID, ssid);
}
// CalDAV settings
public Integer getTimeRangePastDays() { public Integer getTimeRangePastDays() {
String strDays = accountManager.getUserData(account, KEY_TIME_RANGE_PAST_DAYS); String strDays = accountManager.getUserData(account, KEY_TIME_RANGE_PAST_DAYS);
if (strDays != null) { if (strDays != null) {
@ -173,8 +197,7 @@ public class AccountSettings {
} }
public boolean getManageCalendarColors() { public boolean getManageCalendarColors() {
String manage = accountManager.getUserData(account, KEY_MANAGE_CALENDAR_COLORS); return accountManager.getUserData(account, KEY_MANAGE_CALENDAR_COLORS) == null;
return manage == null;
} }
public void setManageCalendarColors(boolean manage) { public void setManageCalendarColors(boolean manage) {

View File

@ -1,29 +0,0 @@
/*
* Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package at.bitfire.davdroid.model;
import android.content.ContentValues;
import lombok.ToString;
@ToString
public class HomeSet {
public long id, serviceID;
public String URL;
public static HomeSet fromDB(ContentValues values) {
HomeSet homeSet = new HomeSet();
homeSet.id = values.getAsLong(ServiceDB.HomeSets.ID);
homeSet.serviceID = values.getAsLong(ServiceDB.HomeSets.SERVICE_ID);
homeSet.URL = values.getAsString(ServiceDB.HomeSets.URL);
return homeSet;
}
}

View File

@ -1,29 +0,0 @@
/*
* Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package at.bitfire.davdroid.model;
import android.content.ContentValues;
public class Service {
public long id;
public String accountName, service, principal;
public long lastRefresh;
public static Service fromDB(ContentValues values) {
Service service = new Service();
service.id = values.getAsLong(ServiceDB.Services.ID);
service.accountName = values.getAsString(ServiceDB.Services.ACCOUNT_NAME);
service.service = values.getAsString(ServiceDB.Services.SERVICE);
service.principal = values.getAsString(ServiceDB.Services.PRINCIPAL);
return service;
}
}

View File

@ -9,12 +9,9 @@
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.syncadapter;
import android.accounts.Account; import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.SyncResult; import android.content.SyncResult;
import android.os.Bundle; import android.os.Bundle;
import android.provider.CalendarContract.Calendars;
import android.text.TextUtils;
import org.apache.commons.codec.Charsets; import org.apache.commons.codec.Charsets;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -34,12 +31,11 @@ import at.bitfire.dav4android.DavCalendar;
import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.DavResource;
import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.property.CalendarColor;
import at.bitfire.dav4android.property.CalendarData; import at.bitfire.dav4android.property.CalendarData;
import at.bitfire.dav4android.property.DisplayName;
import at.bitfire.dav4android.property.GetCTag; import at.bitfire.dav4android.property.GetCTag;
import at.bitfire.dav4android.property.GetContentType; import at.bitfire.dav4android.property.GetContentType;
import at.bitfire.dav4android.property.GetETag; import at.bitfire.dav4android.property.GetETag;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App; import at.bitfire.davdroid.App;
import at.bitfire.davdroid.ArrayUtils; import at.bitfire.davdroid.ArrayUtils;
import at.bitfire.davdroid.Constants; import at.bitfire.davdroid.Constants;
@ -63,8 +59,8 @@ public class CalendarSyncManager extends SyncManager {
protected static final int MAX_MULTIGET = 20; protected static final int MAX_MULTIGET = 20;
public CalendarSyncManager(Context context, Account account, Bundle extras, String authority, SyncResult result, LocalCalendar calendar) throws InvalidAccountException { public CalendarSyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, SyncResult result, LocalCalendar calendar) throws InvalidAccountException {
super(context, account, extras, authority, result, "calendar/" + calendar.getId()); super(context, account, settings, extras, authority, result, "calendar/" + calendar.getId());
localCollection = calendar; localCollection = calendar;
} }

View File

@ -10,6 +10,7 @@ package at.bitfire.davdroid.syncadapter;
import android.accounts.Account; import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter; import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient; import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.SyncResult; import android.content.SyncResult;
@ -56,11 +57,15 @@ public class CalendarsSyncAdapterService extends SyncAdapterService {
super.onPerformSync(account, extras, authority, provider, syncResult); super.onPerformSync(account, extras, authority, provider, syncResult);
try { try {
updateLocalCalendars(provider, account); AccountSettings settings = new AccountSettings(getContext(), account);
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings))
return;
updateLocalCalendars(provider, account, settings);
for (LocalCalendar calendar : (LocalCalendar[])LocalCalendar.find(account, provider, LocalCalendar.Factory.INSTANCE, CalendarContract.Calendars.SYNC_EVENTS + "!=0", null)) { for (LocalCalendar calendar : (LocalCalendar[])LocalCalendar.find(account, provider, LocalCalendar.Factory.INSTANCE, CalendarContract.Calendars.SYNC_EVENTS + "!=0", null)) {
App.log.info("Synchronizing calendar #" + calendar.getId() + ", URL: " + calendar.getName()); App.log.info("Synchronizing calendar #" + calendar.getId() + ", URL: " + calendar.getName());
CalendarSyncManager syncManager = new CalendarSyncManager(getContext(), account, extras, authority, syncResult, calendar); CalendarSyncManager syncManager = new CalendarSyncManager(getContext(), account, settings, extras, authority, syncResult, calendar);
syncManager.performSync(); syncManager.performSync();
} }
} catch (CalendarStorageException e) { } catch (CalendarStorageException e) {
@ -73,7 +78,7 @@ public class CalendarsSyncAdapterService extends SyncAdapterService {
App.log.info("Calendar sync complete"); App.log.info("Calendar sync complete");
} }
private void updateLocalCalendars(ContentProviderClient provider, Account account) throws CalendarStorageException, InvalidAccountException { private void updateLocalCalendars(ContentProviderClient provider, Account account, AccountSettings settings) throws CalendarStorageException {
SQLiteOpenHelper dbHelper = new ServiceDB.OpenHelper(getContext()); SQLiteOpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
try { try {
// enumerate remote and local calendars // enumerate remote and local calendars
@ -83,7 +88,6 @@ public class CalendarsSyncAdapterService extends SyncAdapterService {
LocalCalendar[] local = (LocalCalendar[])LocalCalendar.find(account, provider, LocalCalendar.Factory.INSTANCE, null, null); LocalCalendar[] local = (LocalCalendar[])LocalCalendar.find(account, provider, LocalCalendar.Factory.INSTANCE, null, null);
AccountSettings settings = new AccountSettings(getContext(), account);
boolean updateColors = settings.getManageCalendarColors(); boolean updateColors = settings.getManageCalendarColors();
// delete obsolete local calendar // delete obsolete local calendar

View File

@ -10,6 +10,7 @@ package at.bitfire.davdroid.syncadapter;
import android.accounts.Account; import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter; import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient; import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.SyncResult; import android.content.SyncResult;
@ -23,6 +24,7 @@ import android.support.annotation.Nullable;
import java.util.logging.Level; import java.util.logging.Level;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App; import at.bitfire.davdroid.App;
import at.bitfire.davdroid.InvalidAccountException; import at.bitfire.davdroid.InvalidAccountException;
import at.bitfire.davdroid.model.CollectionInfo; import at.bitfire.davdroid.model.CollectionInfo;
@ -50,13 +52,17 @@ public class ContactsSyncAdapterService extends SyncAdapterService {
SQLiteOpenHelper dbHelper = new ServiceDB.OpenHelper(getContext()); SQLiteOpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
try { try {
AccountSettings settings = new AccountSettings(getContext(), account);
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings))
return;
SQLiteDatabase db = dbHelper.getReadableDatabase(); SQLiteDatabase db = dbHelper.getReadableDatabase();
Long service = getService(db, account); Long service = getService(db, account);
if (service != null) { if (service != null) {
CollectionInfo remote = remoteAddressBook(db, service); CollectionInfo remote = remoteAddressBook(db, service);
if (remote != null) if (remote != null)
try { try {
ContactsSyncManager syncManager = new ContactsSyncManager(getContext(), account, extras, authority, provider, syncResult, remote); ContactsSyncManager syncManager = new ContactsSyncManager(getContext(), account, settings, extras, authority, provider, syncResult, remote);
syncManager.performSync(); syncManager.performSync();
} catch(InvalidAccountException e) { } catch(InvalidAccountException e) {
App.log.log(Level.SEVERE, "Couldn't get account settings", e); App.log.log(Level.SEVERE, "Couldn't get account settings", e);
@ -65,6 +71,8 @@ public class ContactsSyncAdapterService extends SyncAdapterService {
App.log.info("No address book collection selected for synchronization"); App.log.info("No address book collection selected for synchronization");
} else } else
App.log.info("No CardDAV service found in DB"); App.log.info("No CardDAV service found in DB");
} catch (InvalidAccountException e) {
App.log.log(Level.SEVERE, "Couldn't get account settings", e);
} finally { } finally {
dbHelper.close(); dbHelper.close();
} }

View File

@ -37,6 +37,7 @@ import at.bitfire.dav4android.property.GetCTag;
import at.bitfire.dav4android.property.GetContentType; import at.bitfire.dav4android.property.GetContentType;
import at.bitfire.dav4android.property.GetETag; import at.bitfire.dav4android.property.GetETag;
import at.bitfire.dav4android.property.SupportedAddressData; import at.bitfire.dav4android.property.SupportedAddressData;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App; import at.bitfire.davdroid.App;
import at.bitfire.davdroid.ArrayUtils; import at.bitfire.davdroid.ArrayUtils;
import at.bitfire.davdroid.Constants; import at.bitfire.davdroid.Constants;
@ -71,8 +72,8 @@ public class ContactsSyncManager extends SyncManager {
private boolean hasVCard4; private boolean hasVCard4;
public ContactsSyncManager(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult result, CollectionInfo remote) throws InvalidAccountException { public ContactsSyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, ContentProviderClient provider, SyncResult result, CollectionInfo remote) throws InvalidAccountException {
super(context, account, extras, authority, result, "addressBook"); super(context, account, settings, extras, authority, result, "addressBook");
this.provider = provider; this.provider = provider;
this.remote = remote; this.remote = remote;
} }

View File

@ -16,9 +16,19 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SyncResult; import android.content.SyncResult;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.net.ConnectivityManagerCompat;
import android.text.TextUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import java.util.logging.Level; import java.util.logging.Level;
@ -46,11 +56,39 @@ public abstract class SyncAdapterService extends Service {
@Override @Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
App.log.info("Starting " + authority + " sync"); App.log.info("Sync for " + authority + " has been initiated");
// required for dav4android (ServiceLoader) // required for dav4android (ServiceLoader)
Thread.currentThread().setContextClassLoader(getContext().getClassLoader()); Thread.currentThread().setContextClassLoader(getContext().getClassLoader());
} }
protected boolean checkSyncConditions(@NonNull AccountSettings settings) {
if (settings.getSyncWifiOnly()) {
ConnectivityManager cm = (ConnectivityManager)getContext().getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo network = cm.getActiveNetworkInfo();
if (network == null) {
App.log.info("No network available, stopping");
return false;
}
if (network.getType() != ConnectivityManager.TYPE_WIFI || !network.isConnected()) {
App.log.info("Not on connected WiFi, stopping");
return false;
}
String onlySSID = settings.getSyncWifiOnlySSID();
if (onlySSID != null) {
onlySSID = "\"" + onlySSID + "\"";
WifiManager wifi = (WifiManager)getContext().getSystemService(WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
if (info == null || !onlySSID.equals(info.getSSID())) {
App.log.info("Connected to wrong WiFi network (" + info.getSSID() + ", required: " + onlySSID + "), ignoring");
return false;
}
}
}
return true;
}
} }
} }

View File

@ -98,16 +98,14 @@ abstract public class SyncManager {
public SyncManager(Context context, Account account, Bundle extras, String authority, SyncResult syncResult, String uniqueCollectionId) throws InvalidAccountException { public SyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, SyncResult syncResult, String uniqueCollectionId) throws InvalidAccountException {
this.context = context; this.context = context;
this.account = account; this.account = account;
this.settings = settings;
this.extras = extras; this.extras = extras;
this.authority = authority; this.authority = authority;
this.syncResult = syncResult; this.syncResult = syncResult;
// get account settings (for sync interval etc.)
settings = new AccountSettings(context, account);
// create HttpClient with given logger // create HttpClient with given logger
httpClient = HttpClient.create(context, account); httpClient = HttpClient.create(context, account);

View File

@ -10,6 +10,7 @@ package at.bitfire.davdroid.syncadapter;
import android.accounts.Account; import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter; import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient; import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.SyncResult; import android.content.SyncResult;
@ -25,6 +26,7 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App; import at.bitfire.davdroid.App;
import at.bitfire.davdroid.InvalidAccountException; import at.bitfire.davdroid.InvalidAccountException;
import at.bitfire.davdroid.model.CollectionInfo; import at.bitfire.davdroid.model.CollectionInfo;
@ -59,11 +61,15 @@ public class TasksSyncAdapterService extends SyncAdapterService {
if (provider == null) if (provider == null)
throw new CalendarStorageException("Couldn't access OpenTasks provider"); throw new CalendarStorageException("Couldn't access OpenTasks provider");
AccountSettings settings = new AccountSettings(getContext(), account);
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings))
return;
updateLocalTaskLists(provider, account); updateLocalTaskLists(provider, account);
for (LocalTaskList taskList : (LocalTaskList[])LocalTaskList.find(account, provider, LocalTaskList.Factory.INSTANCE, null, null)) { for (LocalTaskList taskList : (LocalTaskList[])LocalTaskList.find(account, provider, LocalTaskList.Factory.INSTANCE, null, null)) {
App.log.info("Synchronizing task list #" + taskList.getId() + ", URL: " + taskList.getSyncId()); App.log.info("Synchronizing task list #" + taskList.getId() + ", URL: " + taskList.getSyncId());
TasksSyncManager syncManager = new TasksSyncManager(getContext(), account, extras, authority, provider, syncResult, taskList); TasksSyncManager syncManager = new TasksSyncManager(getContext(), account, settings, extras, authority, provider, syncResult, taskList);
syncManager.performSync(); syncManager.performSync();
} }
} catch (CalendarStorageException e) { } catch (CalendarStorageException e) {

View File

@ -9,22 +9,17 @@
package at.bitfire.davdroid.syncadapter; package at.bitfire.davdroid.syncadapter;
import android.accounts.Account; import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.SyncResult; import android.content.SyncResult;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils;
import org.apache.commons.codec.Charsets; import org.apache.commons.codec.Charsets;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.dmfs.provider.tasks.TaskContract.TaskLists;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -34,12 +29,11 @@ import at.bitfire.dav4android.DavCalendar;
import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.DavResource;
import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.property.CalendarColor;
import at.bitfire.dav4android.property.CalendarData; import at.bitfire.dav4android.property.CalendarData;
import at.bitfire.dav4android.property.DisplayName;
import at.bitfire.dav4android.property.GetCTag; import at.bitfire.dav4android.property.GetCTag;
import at.bitfire.dav4android.property.GetContentType; import at.bitfire.dav4android.property.GetContentType;
import at.bitfire.dav4android.property.GetETag; import at.bitfire.dav4android.property.GetETag;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App; import at.bitfire.davdroid.App;
import at.bitfire.davdroid.ArrayUtils; import at.bitfire.davdroid.ArrayUtils;
import at.bitfire.davdroid.Constants; import at.bitfire.davdroid.Constants;
@ -65,8 +59,8 @@ public class TasksSyncManager extends SyncManager {
final protected TaskProvider provider; final protected TaskProvider provider;
public TasksSyncManager(Context context, Account account, Bundle extras, String authority, TaskProvider provider, SyncResult result, LocalTaskList taskList) throws InvalidAccountException { public TasksSyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, TaskProvider provider, SyncResult result, LocalTaskList taskList) throws InvalidAccountException {
super(context, account, extras, authority, result, "taskList/" + taskList.getId()); super(context, account, settings, extras, authority, result, "taskList/" + taskList.getId());
this.provider = provider; this.provider = provider;
localCollection = taskList; localCollection = taskList;
} }

View File

@ -11,6 +11,9 @@ package at.bitfire.davdroid.ui;
import android.accounts.Account; import android.accounts.Account;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.provider.CalendarContract; import android.provider.CalendarContract;
import android.provider.ContactsContract; import android.provider.ContactsContract;
@ -22,8 +25,12 @@ import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat; import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.SwitchPreferenceCompat; import android.support.v7.preference.SwitchPreferenceCompat;
import android.text.TextUtils;
import android.view.MenuItem; import android.view.MenuItem;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import at.bitfire.davdroid.AccountSettings; import at.bitfire.davdroid.AccountSettings;
@ -183,6 +190,34 @@ public class AccountSettingsActivity extends AppCompatActivity {
prefSyncTasks.setSummary(R.string.settings_sync_summary_not_available); prefSyncTasks.setSummary(R.string.settings_sync_summary_not_available);
} }
final SwitchPreferenceCompat prefWifiOnly = (SwitchPreferenceCompat)findPreference("sync_wifi_only");
prefWifiOnly.setChecked(settings.getSyncWifiOnly());
prefWifiOnly.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object wifiOnly) {
settings.setSyncWiFiOnly((Boolean)wifiOnly);
refresh();
return false;
}
});
final EditTextPreference prefWifiOnlySSID = (EditTextPreference)findPreference("sync_wifi_only_ssid");
final String onlySSID = settings.getSyncWifiOnlySSID();
prefWifiOnlySSID.setText(onlySSID);
if (onlySSID != null)
prefWifiOnlySSID.setSummary(getString(R.string.settings_sync_wifi_only_ssid_on, onlySSID));
else
prefWifiOnlySSID.setSummary(R.string.settings_sync_wifi_only_ssid_off);
prefWifiOnlySSID.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String ssid = (String)newValue;
settings.setSyncWifiOnlySSID(!TextUtils.isEmpty(ssid) ? ssid : null);
refresh(); return false;
}
});
// category: CalDAV
final EditTextPreference prefTimeRangePastDays = (EditTextPreference)findPreference("caldav_time_range_past_days"); final EditTextPreference prefTimeRangePastDays = (EditTextPreference)findPreference("caldav_time_range_past_days");
Integer pastDays = settings.getTimeRangePastDays(); Integer pastDays = settings.getTimeRangePastDays();
if (pastDays != null) { if (pastDays != null) {
@ -212,7 +247,8 @@ public class AccountSettingsActivity extends AppCompatActivity {
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
settings.setManageCalendarColors((Boolean)newValue); settings.setManageCalendarColors((Boolean)newValue);
refresh(); return false; refresh();
return false;
} }
}); });

View File

@ -32,6 +32,7 @@ import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App; import at.bitfire.davdroid.App;
import at.bitfire.davdroid.Constants; import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.DavService; import at.bitfire.davdroid.DavService;
import at.bitfire.davdroid.InvalidAccountException;
import at.bitfire.davdroid.R; import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.CollectionInfo; import at.bitfire.davdroid.model.CollectionInfo;
import at.bitfire.davdroid.model.ServiceDB.Collections; import at.bitfire.davdroid.model.ServiceDB.Collections;
@ -45,6 +46,7 @@ import lombok.Cleanup;
public class AccountDetailsFragment extends Fragment { public class AccountDetailsFragment extends Fragment {
private static final String KEY_CONFIG = "config"; private static final String KEY_CONFIG = "config";
private static final int DEFAULT_SYNC_INTERVAL = 4 * 3600; // 4 hours
public static AccountDetailsFragment newInstance(DavResourceFinder.Configuration config) { public static AccountDetailsFragment newInstance(DavResourceFinder.Configuration config) {
AccountDetailsFragment frag = new AccountDetailsFragment(); AccountDetailsFragment frag = new AccountDetailsFragment();
@ -107,6 +109,8 @@ public class AccountDetailsFragment extends Fragment {
SQLiteDatabase db = dbHelper.getWritableDatabase(); SQLiteDatabase db = dbHelper.getWritableDatabase();
db.beginTransactionNonExclusive(); db.beginTransactionNonExclusive();
try { try {
AccountSettings settings = new AccountSettings(getContext(), account);
Intent refreshIntent = new Intent(getActivity(), DavService.class); Intent refreshIntent = new Intent(getActivity(), DavService.class);
refreshIntent.setAction(DavService.ACTION_REFRESH_COLLECTIONS); refreshIntent.setAction(DavService.ACTION_REFRESH_COLLECTIONS);
@ -116,7 +120,7 @@ public class AccountDetailsFragment extends Fragment {
getActivity().startService(refreshIntent); getActivity().startService(refreshIntent);
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true); settings.setSyncInterval(ContactsContract.AUTHORITY, DEFAULT_SYNC_INTERVAL);
} else } else
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0); ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
@ -126,12 +130,12 @@ public class AccountDetailsFragment extends Fragment {
getActivity().startService(refreshIntent); getActivity().startService(refreshIntent);
ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 1); ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 1);
ContentResolver.setSyncAutomatically(account, CalendarContract.AUTHORITY, true); settings.setSyncInterval(CalendarContract.AUTHORITY, DEFAULT_SYNC_INTERVAL);
if (LocalTaskList.tasksProviderAvailable(getContext().getContentResolver())) { if (LocalTaskList.tasksProviderAvailable(getContext().getContentResolver())) {
// will only do something if OpenTasks is installed and accessible // will only do something if OpenTasks is installed and accessible
ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 1); ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 1);
ContentResolver.setSyncAutomatically(account, TaskProvider.ProviderName.OpenTasks.authority, true); settings.setSyncInterval(TaskProvider.ProviderName.OpenTasks.authority, DEFAULT_SYNC_INTERVAL);
} else } else
// If OpenTasks is installed after DAVdroid, DAVdroid won't get task permissions and crash at every task sync // If OpenTasks is installed after DAVdroid, DAVdroid won't get task permissions and crash at every task sync
// unless we disable task sync here (before OpenTasks is available). // unless we disable task sync here (before OpenTasks is available).
@ -142,6 +146,8 @@ public class AccountDetailsFragment extends Fragment {
} }
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} catch(InvalidAccountException e) {
App.log.log(Level.SEVERE, "Couldn't access account settings", e);
} finally { } finally {
db.endTransaction(); db.endTransaction();
} }

View File

@ -166,6 +166,13 @@
<item quantity="other">Events more than %d days in the past will be ignored</item> <item quantity="other">Events more than %d days in the past will be ignored</item>
</plurals> </plurals>
<string name="settings_sync_time_range_past_message">Events which are more than this number of days in the past will be ignored (may be 0). Leave blank to synchronize all events.</string> <string name="settings_sync_time_range_past_message">Events which are more than this number of days in the past will be ignored (may be 0). Leave blank to synchronize all events.</string>
<string name="settings_sync_wifi_only">Sync over WiFi only</string>
<string name="settings_sync_wifi_only_on">Synchronization is restricted to WiFi connections</string>
<string name="settings_sync_wifi_only_off">Connection type is not taken into consideration</string>
<string name="settings_sync_wifi_only_ssid">WiFi SSID restriction</string>
<string name="settings_sync_wifi_only_ssid_on">Will only synchronize over %s</string>
<string name="settings_sync_wifi_only_ssid_off">All WiFi connections may be used</string>
<string name="settings_sync_wifi_only_ssid_message">Enter the name of a WiFi network (SSID) to restrict synchronization to this network, or leave blank for all WiFi connections.</string>
<string name="settings_manage_calendar_colors">Manage calendar colors</string> <string name="settings_manage_calendar_colors">Manage calendar colors</string>
<string name="settings_manage_calendar_colors_on">Calendar colors are managed by DAVdroid</string> <string name="settings_manage_calendar_colors_on">Calendar colors are managed by DAVdroid</string>
<string name="settings_manage_calendar_colors_off">Calendar colors are not set by DAVdroid</string> <string name="settings_manage_calendar_colors_off">Calendar colors are not set by DAVdroid</string>

View File

@ -57,6 +57,25 @@
android:entries="@array/settings_sync_interval_names" android:entries="@array/settings_sync_interval_names"
android:entryValues="@array/settings_sync_interval_seconds" /> android:entryValues="@array/settings_sync_interval_seconds" />
<SwitchPreferenceCompat
android:key="sync_wifi_only"
android:persistent="false"
android:title="@string/settings_sync_wifi_only"
android:summaryOn="@string/settings_sync_wifi_only_on"
android:summaryOff="@string/settings_sync_wifi_only_off"
/>
<EditTextPreference
android:key="sync_wifi_only_ssid"
android:dependency="sync_wifi_only"
android:persistent="false"
android:title="@string/settings_sync_wifi_only_ssid"
android:dialogMessage="@string/settings_sync_wifi_only_ssid_message"/>
</PreferenceCategory>
<PreferenceCategory android:title="CalDAV">
<EditTextPreference <EditTextPreference
android:key="caldav_time_range_past_days" android:key="caldav_time_range_past_days"
android:persistent="false" android:persistent="false"
@ -71,6 +90,6 @@
android:summaryOn="@string/settings_manage_calendar_colors_on" android:summaryOn="@string/settings_manage_calendar_colors_on"
android:summaryOff="@string/settings_manage_calendar_colors_off"/> android:summaryOff="@string/settings_manage_calendar_colors_off"/>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>