From 6ffa6fa9a75104aad4a7305ac8715e6f6793dfce Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Wed, 6 Apr 2016 21:04:16 +0200 Subject: [PATCH] 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 --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 2 + .../at/bitfire/davdroid/AccountSettings.java | 33 ++++++++++++--- .../at/bitfire/davdroid/model/HomeSet.java | 29 -------------- .../at/bitfire/davdroid/model/Service.java | 29 -------------- .../syncadapter/CalendarSyncManager.java | 10 ++--- .../CalendarsSyncAdapterService.java | 12 ++++-- .../ContactsSyncAdapterService.java | 10 ++++- .../syncadapter/ContactsSyncManager.java | 5 ++- .../syncadapter/SyncAdapterService.java | 40 ++++++++++++++++++- .../davdroid/syncadapter/SyncManager.java | 6 +-- .../syncadapter/TasksSyncAdapterService.java | 8 +++- .../syncadapter/TasksSyncManager.java | 12 ++---- .../davdroid/ui/AccountSettingsActivity.java | 38 +++++++++++++++++- .../ui/setup/AccountDetailsFragment.java | 12 ++++-- app/src/main/res/values/strings.xml | 7 ++++ app/src/main/res/xml/settings_account.xml | 21 +++++++++- 17 files changed, 179 insertions(+), 99 deletions(-) delete mode 100644 app/src/main/java/at/bitfire/davdroid/model/HomeSet.java delete mode 100644 app/src/main/java/at/bitfire/davdroid/model/Service.java diff --git a/app/build.gradle b/app/build.gradle index a6fffa64..55ab2691 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { minSdkVersion 14 targetSdkVersion 22 - versionCode 95 - versionName "1.0.5" + versionCode 96 + versionName "1.0.6" buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index aa441cc2..d46b7b1a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,8 @@ android:installLocation="internalOnly"> + + diff --git a/app/src/main/java/at/bitfire/davdroid/AccountSettings.java b/app/src/main/java/at/bitfire/davdroid/AccountSettings.java index c001aef3..9b895c43 100644 --- a/app/src/main/java/at/bitfire/davdroid/AccountSettings.java +++ b/app/src/main/java/at/bitfire/davdroid/AccountSettings.java @@ -24,6 +24,7 @@ import android.os.Bundle; import android.provider.CalendarContract; import android.provider.ContactsContract; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.app.NotificationCompat; import android.text.TextUtils; @@ -49,10 +50,13 @@ import okhttp3.HttpUrl; public class AccountSettings { private final static int CURRENT_VERSION = 3; private final static String - KEY_SETTINGS_VERSION = "version", + KEY_SETTINGS_VERSION = "version", - KEY_USERNAME = "user_name", - KEY_AUTH_PREEMPTIVE = "auth_preemptive"; + KEY_USERNAME = "user_name", + 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] 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() { String strDays = accountManager.getUserData(account, KEY_TIME_RANGE_PAST_DAYS); if (strDays != null) { @@ -173,8 +197,7 @@ public class AccountSettings { } public boolean getManageCalendarColors() { - String manage = accountManager.getUserData(account, KEY_MANAGE_CALENDAR_COLORS); - return manage == null; + return accountManager.getUserData(account, KEY_MANAGE_CALENDAR_COLORS) == null; } public void setManageCalendarColors(boolean manage) { diff --git a/app/src/main/java/at/bitfire/davdroid/model/HomeSet.java b/app/src/main/java/at/bitfire/davdroid/model/HomeSet.java deleted file mode 100644 index 757eeaa0..00000000 --- a/app/src/main/java/at/bitfire/davdroid/model/HomeSet.java +++ /dev/null @@ -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; - } - -} diff --git a/app/src/main/java/at/bitfire/davdroid/model/Service.java b/app/src/main/java/at/bitfire/davdroid/model/Service.java deleted file mode 100644 index 1cc8912b..00000000 --- a/app/src/main/java/at/bitfire/davdroid/model/Service.java +++ /dev/null @@ -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; - } - -} diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.java index 72d0b0df..dde2904c 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.java @@ -9,12 +9,9 @@ package at.bitfire.davdroid.syncadapter; import android.accounts.Account; -import android.content.ContentValues; import android.content.Context; import android.content.SyncResult; import android.os.Bundle; -import android.provider.CalendarContract.Calendars; -import android.text.TextUtils; import org.apache.commons.codec.Charsets; import org.apache.commons.lang3.StringUtils; @@ -34,12 +31,11 @@ import at.bitfire.dav4android.DavCalendar; import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.HttpException; -import at.bitfire.dav4android.property.CalendarColor; import at.bitfire.dav4android.property.CalendarData; -import at.bitfire.dav4android.property.DisplayName; import at.bitfire.dav4android.property.GetCTag; import at.bitfire.dav4android.property.GetContentType; import at.bitfire.dav4android.property.GetETag; +import at.bitfire.davdroid.AccountSettings; import at.bitfire.davdroid.App; import at.bitfire.davdroid.ArrayUtils; import at.bitfire.davdroid.Constants; @@ -63,8 +59,8 @@ public class CalendarSyncManager extends SyncManager { protected static final int MAX_MULTIGET = 20; - public CalendarSyncManager(Context context, Account account, Bundle extras, String authority, SyncResult result, LocalCalendar calendar) throws InvalidAccountException { - super(context, account, extras, authority, result, "calendar/" + calendar.getId()); + public CalendarSyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, SyncResult result, LocalCalendar calendar) throws InvalidAccountException { + super(context, account, settings, extras, authority, result, "calendar/" + calendar.getId()); localCollection = calendar; } diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.java index 23231421..8e01f52b 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.java @@ -10,6 +10,7 @@ package at.bitfire.davdroid.syncadapter; import android.accounts.Account; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; +import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.SyncResult; @@ -56,11 +57,15 @@ public class CalendarsSyncAdapterService extends SyncAdapterService { super.onPerformSync(account, extras, authority, provider, syncResult); 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)) { 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(); } } catch (CalendarStorageException e) { @@ -73,7 +78,7 @@ public class CalendarsSyncAdapterService extends SyncAdapterService { 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()); try { // 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); - AccountSettings settings = new AccountSettings(getContext(), account); boolean updateColors = settings.getManageCalendarColors(); // delete obsolete local calendar diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncAdapterService.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncAdapterService.java index 5c733fcd..c179d908 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncAdapterService.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncAdapterService.java @@ -10,6 +10,7 @@ package at.bitfire.davdroid.syncadapter; import android.accounts.Account; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; +import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.SyncResult; @@ -23,6 +24,7 @@ import android.support.annotation.Nullable; import java.util.logging.Level; +import at.bitfire.davdroid.AccountSettings; import at.bitfire.davdroid.App; import at.bitfire.davdroid.InvalidAccountException; import at.bitfire.davdroid.model.CollectionInfo; @@ -50,13 +52,17 @@ public class ContactsSyncAdapterService extends SyncAdapterService { SQLiteOpenHelper dbHelper = new ServiceDB.OpenHelper(getContext()); try { + AccountSettings settings = new AccountSettings(getContext(), account); + if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings)) + return; + SQLiteDatabase db = dbHelper.getReadableDatabase(); Long service = getService(db, account); if (service != null) { CollectionInfo remote = remoteAddressBook(db, service); if (remote != null) 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(); } catch(InvalidAccountException 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"); } else App.log.info("No CardDAV service found in DB"); + } catch (InvalidAccountException e) { + App.log.log(Level.SEVERE, "Couldn't get account settings", e); } finally { dbHelper.close(); } diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.java index e7da7443..57041a81 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/ContactsSyncManager.java @@ -37,6 +37,7 @@ import at.bitfire.dav4android.property.GetCTag; import at.bitfire.dav4android.property.GetContentType; import at.bitfire.dav4android.property.GetETag; import at.bitfire.dav4android.property.SupportedAddressData; +import at.bitfire.davdroid.AccountSettings; import at.bitfire.davdroid.App; import at.bitfire.davdroid.ArrayUtils; import at.bitfire.davdroid.Constants; @@ -71,8 +72,8 @@ public class ContactsSyncManager extends SyncManager { private boolean hasVCard4; - public ContactsSyncManager(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult result, CollectionInfo remote) throws InvalidAccountException { - super(context, account, extras, authority, result, "addressBook"); + public ContactsSyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, ContentProviderClient provider, SyncResult result, CollectionInfo remote) throws InvalidAccountException { + super(context, account, settings, extras, authority, result, "addressBook"); this.provider = provider; this.remote = remote; } diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncAdapterService.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncAdapterService.java index ad37e90c..447c0189 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncAdapterService.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncAdapterService.java @@ -16,9 +16,19 @@ import android.content.Context; import android.content.Intent; import android.content.SyncResult; 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.IBinder; +import android.support.annotation.NonNull; 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; @@ -46,11 +56,39 @@ public abstract class SyncAdapterService extends Service { @Override 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) 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; + } + } } diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.java index 354f458b..1e80e554 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.java @@ -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.account = account; + this.settings = settings; this.extras = extras; this.authority = authority; this.syncResult = syncResult; - // get account settings (for sync interval etc.) - settings = new AccountSettings(context, account); - // create HttpClient with given logger httpClient = HttpClient.create(context, account); diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncAdapterService.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncAdapterService.java index 59073388..52f18e91 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncAdapterService.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncAdapterService.java @@ -10,6 +10,7 @@ package at.bitfire.davdroid.syncadapter; import android.accounts.Account; import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; +import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.SyncResult; @@ -25,6 +26,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Level; +import at.bitfire.davdroid.AccountSettings; import at.bitfire.davdroid.App; import at.bitfire.davdroid.InvalidAccountException; import at.bitfire.davdroid.model.CollectionInfo; @@ -59,11 +61,15 @@ public class TasksSyncAdapterService extends SyncAdapterService { if (provider == null) 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); for (LocalTaskList taskList : (LocalTaskList[])LocalTaskList.find(account, provider, LocalTaskList.Factory.INSTANCE, null, null)) { 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(); } } catch (CalendarStorageException e) { diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.java index 0c76136c..759abdd0 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/TasksSyncManager.java @@ -9,22 +9,17 @@ package at.bitfire.davdroid.syncadapter; import android.accounts.Account; -import android.content.ContentValues; import android.content.Context; import android.content.SyncResult; import android.os.Bundle; -import android.text.TextUtils; import org.apache.commons.codec.Charsets; import org.apache.commons.lang3.StringUtils; -import org.dmfs.provider.tasks.TaskContract.TaskLists; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; -import java.util.Calendar; -import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -34,12 +29,11 @@ import at.bitfire.dav4android.DavCalendar; import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.HttpException; -import at.bitfire.dav4android.property.CalendarColor; import at.bitfire.dav4android.property.CalendarData; -import at.bitfire.dav4android.property.DisplayName; import at.bitfire.dav4android.property.GetCTag; import at.bitfire.dav4android.property.GetContentType; import at.bitfire.dav4android.property.GetETag; +import at.bitfire.davdroid.AccountSettings; import at.bitfire.davdroid.App; import at.bitfire.davdroid.ArrayUtils; import at.bitfire.davdroid.Constants; @@ -65,8 +59,8 @@ public class TasksSyncManager extends SyncManager { final protected TaskProvider provider; - public TasksSyncManager(Context context, Account account, Bundle extras, String authority, TaskProvider provider, SyncResult result, LocalTaskList taskList) throws InvalidAccountException { - super(context, account, extras, authority, result, "taskList/" + taskList.getId()); + public TasksSyncManager(Context context, Account account, AccountSettings settings, Bundle extras, String authority, TaskProvider provider, SyncResult result, LocalTaskList taskList) throws InvalidAccountException { + super(context, account, settings, extras, authority, result, "taskList/" + taskList.getId()); this.provider = provider; localCollection = taskList; } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/AccountSettingsActivity.java b/app/src/main/java/at/bitfire/davdroid/ui/AccountSettingsActivity.java index 6542e0da..41dfdbdc 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/AccountSettingsActivity.java +++ b/app/src/main/java/at/bitfire/davdroid/ui/AccountSettingsActivity.java @@ -11,6 +11,9 @@ package at.bitfire.davdroid.ui; import android.accounts.Account; import android.content.DialogInterface; 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.provider.CalendarContract; 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.PreferenceFragmentCompat; import android.support.v7.preference.SwitchPreferenceCompat; +import android.text.TextUtils; import android.view.MenuItem; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import java.util.logging.Level; import at.bitfire.davdroid.AccountSettings; @@ -183,6 +190,34 @@ public class AccountSettingsActivity extends AppCompatActivity { 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"); Integer pastDays = settings.getTimeRangePastDays(); if (pastDays != null) { @@ -212,7 +247,8 @@ public class AccountSettingsActivity extends AppCompatActivity { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { settings.setManageCalendarColors((Boolean)newValue); - refresh(); return false; + refresh(); + return false; } }); diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.java b/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.java index 311dff70..21b3bbb2 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.java +++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.java @@ -32,6 +32,7 @@ import at.bitfire.davdroid.AccountSettings; import at.bitfire.davdroid.App; import at.bitfire.davdroid.Constants; import at.bitfire.davdroid.DavService; +import at.bitfire.davdroid.InvalidAccountException; import at.bitfire.davdroid.R; import at.bitfire.davdroid.model.CollectionInfo; import at.bitfire.davdroid.model.ServiceDB.Collections; @@ -45,6 +46,7 @@ import lombok.Cleanup; public class AccountDetailsFragment extends Fragment { 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) { AccountDetailsFragment frag = new AccountDetailsFragment(); @@ -107,6 +109,8 @@ public class AccountDetailsFragment extends Fragment { SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransactionNonExclusive(); try { + AccountSettings settings = new AccountSettings(getContext(), account); + Intent refreshIntent = new Intent(getActivity(), DavService.class); refreshIntent.setAction(DavService.ACTION_REFRESH_COLLECTIONS); @@ -116,7 +120,7 @@ public class AccountDetailsFragment extends Fragment { getActivity().startService(refreshIntent); ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); - ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true); + settings.setSyncInterval(ContactsContract.AUTHORITY, DEFAULT_SYNC_INTERVAL); } else ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0); @@ -126,12 +130,12 @@ public class AccountDetailsFragment extends Fragment { getActivity().startService(refreshIntent); ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 1); - ContentResolver.setSyncAutomatically(account, CalendarContract.AUTHORITY, true); + settings.setSyncInterval(CalendarContract.AUTHORITY, DEFAULT_SYNC_INTERVAL); if (LocalTaskList.tasksProviderAvailable(getContext().getContentResolver())) { // will only do something if OpenTasks is installed and accessible 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 // 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). @@ -142,6 +146,8 @@ public class AccountDetailsFragment extends Fragment { } db.setTransactionSuccessful(); + } catch(InvalidAccountException e) { + App.log.log(Level.SEVERE, "Couldn't access account settings", e); } finally { db.endTransaction(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dbf6fe5b..451b0fa0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -166,6 +166,13 @@ Events more than %d days in the past will be ignored Events which are more than this number of days in the past will be ignored (may be 0). Leave blank to synchronize all events. + Sync over WiFi only + Synchronization is restricted to WiFi connections + Connection type is not taken into consideration + WiFi SSID restriction + Will only synchronize over %s + All WiFi connections may be used + Enter the name of a WiFi network (SSID) to restrict synchronization to this network, or leave blank for all WiFi connections. Manage calendar colors Calendar colors are managed by DAVdroid Calendar colors are not set by DAVdroid diff --git a/app/src/main/res/xml/settings_account.xml b/app/src/main/res/xml/settings_account.xml index 4cff8923..839020e3 100644 --- a/app/src/main/res/xml/settings_account.xml +++ b/app/src/main/res/xml/settings_account.xml @@ -57,6 +57,25 @@ android:entries="@array/settings_sync_interval_names" android:entryValues="@array/settings_sync_interval_seconds" /> + + + + + + + + - +