From 419d7321958622faeea6ca3a08b5f93195e26300 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Wed, 14 Oct 2015 21:45:19 +0200 Subject: [PATCH] Process recurring events, exceptions etc. --- .../java/at/bitfire/davdroid/Constants.java | 2 - .../java/at/bitfire/davdroid/HttpClient.java | 3 - .../davdroid/resource/LocalCalendar.java | 123 ++++++++++++++++-- .../davdroid/resource/LocalCollection.java | 4 +- .../davdroid/resource/LocalContact.java | 2 +- .../bitfire/davdroid/resource/LocalEvent.java | 51 ++++++-- .../syncadapter/CalendarSyncManager.java | 7 + .../CalendarsSyncAdapterService.java | 3 +- .../davdroid/syncadapter/SyncManager.java | 24 +++- .../davdroid/ui/DebugInfoActivity.java | 6 +- app/src/main/res/values-de/strings.xml | 4 +- app/src/main/res/values/strings.xml | 2 +- ical4android | 2 +- 13 files changed, 188 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/Constants.java b/app/src/main/java/at/bitfire/davdroid/Constants.java index 77dc2ec0..fdc02ef6 100644 --- a/app/src/main/java/at/bitfire/davdroid/Constants.java +++ b/app/src/main/java/at/bitfire/davdroid/Constants.java @@ -17,7 +17,5 @@ public class Constants { WEB_URL_HELP = "https://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app", WEB_URL_VIEW_LOGS = "https://github.com/bitfireAT/davdroid/wiki/How-to-view-the-logs"; - //public static final ProdId ICAL_PRODID = new ProdId("-//bitfire web engineering//DAVdroid " + BuildConfig.VERSION_CODE + " (ical4j 2.0-beta1)//EN"); - public static final Logger log = LoggerFactory.getLogger("davdroid"); } diff --git a/app/src/main/java/at/bitfire/davdroid/HttpClient.java b/app/src/main/java/at/bitfire/davdroid/HttpClient.java index faeba00a..931ba661 100644 --- a/app/src/main/java/at/bitfire/davdroid/HttpClient.java +++ b/app/src/main/java/at/bitfire/davdroid/HttpClient.java @@ -118,9 +118,6 @@ public class HttpClient extends OkHttpClient { } } - // don't follow redirects automatically because this may rewrite DAV methods to GET - setFollowRedirects(false); - // set timeouts setConnectTimeout(30, TimeUnit.SECONDS); setWriteTimeout(15, TimeUnit.SECONDS); diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java b/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java index 3401d9d9..c708a0b0 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java @@ -10,10 +10,13 @@ package at.bitfire.davdroid.resource; import android.accounts.Account; import android.content.ContentProviderClient; +import android.content.ContentProviderOperation; import android.content.ContentResolver; +import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.RemoteException; import android.provider.CalendarContract; import android.provider.CalendarContract.Calendars; @@ -22,8 +25,14 @@ import android.provider.CalendarContract.Reminders; import com.google.common.base.Joiner; +import java.io.FileNotFoundException; +import java.util.LinkedList; +import java.util.List; + +import at.bitfire.davdroid.Constants; import at.bitfire.ical4android.AndroidCalendar; import at.bitfire.ical4android.AndroidCalendarFactory; +import at.bitfire.ical4android.BatchOperation; import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.vcard4android.ContactsStorageException; import lombok.Cleanup; @@ -34,9 +43,13 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { public static final String COLUMN_CTAG = Calendars.CAL_SYNC1; + protected static final int + DIRTY_INCREASE_SEQUENCE = 1, + DIRTY_DONT_INCREASE_SEQUENCE = 2; + static String[] BASE_INFO_COLUMNS = new String[] { Events._ID, - LocalEvent.COLUMN_FILENAME, + Events._SYNC_ID, LocalEvent.COLUMN_ETAG }; @@ -59,38 +72,61 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { values.put(Calendars.NAME, info.getURL()); values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle()); values.put(Calendars.CALENDAR_COLOR, info.color != null ? info.color : defaultColor); - values.put(Calendars.CALENDAR_ACCESS_LEVEL, info.readOnly ? Calendars.CAL_ACCESS_READ : Calendars.CAL_ACCESS_OWNER); + + if (info.isReadOnly()) + values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ); + else { + values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER); + values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1); + values.put(Calendars.CAN_ORGANIZER_RESPOND, 1); + } + values.put(Calendars.OWNER_ACCOUNT, account.name); values.put(Calendars.SYNC_EVENTS, 1); + values.put(Calendars.VISIBLE, 1); if (info.timezone != null) { // TODO parse VTIMEZONE // values.put(Calendars.CALENDAR_TIME_ZONE, DateUtils.findAndroidTimezoneID(info.timezone)); } values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT); - values.put(Calendars.ALLOWED_AVAILABILITY, Joiner.on(",").join(Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY)); - values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Joiner.on(",").join(CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE)); + if (Build.VERSION.SDK_INT >= 15) { + values.put(Calendars.ALLOWED_AVAILABILITY, Joiner.on(",").join(Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY)); + values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Joiner.on(",").join(CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE)); + } return create(account, provider, values); } @Override public LocalResource[] getAll() throws CalendarStorageException, ContactsStorageException { - return (LocalEvent[])queryEvents(null, null); + return (LocalEvent[])queryEvents(Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalEvent[] getDeleted() throws CalendarStorageException { - return (LocalEvent[])queryEvents(Events.DELETED + "!=0", null); + return (LocalEvent[])queryEvents(Events.DELETED + "!=0 AND " + Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalEvent[] getWithoutFileName() throws CalendarStorageException { - return (LocalEvent[])queryEvents(LocalEvent.COLUMN_FILENAME + " IS NULL", null); + return (LocalEvent[])queryEvents(Events._SYNC_ID + " IS NULL AND " + Events.ORIGINAL_ID + " IS NULL", null); } @Override - public LocalResource[] getDirty() throws CalendarStorageException { - return (LocalEvent[])queryEvents(Events.DIRTY + "!=0", null); + public LocalResource[] getDirty() throws CalendarStorageException, FileNotFoundException { + List dirty = new LinkedList<>(); + + // get dirty events which are not required to have an increased SEQUENCE value + for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_DONT_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null)) + dirty.add(event); + + // get dirty events which are required to have an increased SEQUENCE value + for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null)) { + event.getEvent().sequence++; + dirty.add(event); + } + + return dirty.toArray(new LocalResource[dirty.size()]); } @@ -117,6 +153,75 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { } } + public void processDirtyExceptions() throws CalendarStorageException { + // process deleted exceptions + Constants.log.info("Processing deleted exceptions"); + try { + @Cleanup Cursor cursor = provider.query( + syncAdapterURI(Events.CONTENT_URI), + new String[] { Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE }, + Events.DELETED + "!=0 AND " + Events.ORIGINAL_ID + " IS NOT NULL", null, null); + while (cursor != null && cursor.moveToNext()) { + Constants.log.debug("Found deleted exception, removing; then re-schuling original event"); + long id = cursor.getLong(0), // can't be null (by definition) + originalID = cursor.getLong(1); // can't be null (by query) + int sequence = cursor.isNull(2) ? 0 : cursor.getInt(2); + + // get original event's SEQUENCE + @Cleanup Cursor cursor2 = provider.query( + syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)), + new String[] { LocalEvent.COLUMN_SEQUENCE }, + null, null, null); + int originalSequence = cursor.isNull(0) ? 0 : cursor.getInt(0); + + BatchOperation batch = new BatchOperation(provider); + // re-schedule original event and set it to DIRTY + batch.enqueue(ContentProviderOperation.newUpdate( + syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) + .withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence) + .withValue(Events.DIRTY, DIRTY_INCREASE_SEQUENCE) + .build()); + // remove exception + batch.enqueue(ContentProviderOperation.newDelete( + syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))).build()); + batch.commit(); + } + } catch (RemoteException e) { + throw new CalendarStorageException("Couldn't process locally modified exception", e); + } + + // process dirty exceptions + Constants.log.info("Processing dirty exceptions"); + try { + @Cleanup Cursor cursor = provider.query( + syncAdapterURI(Events.CONTENT_URI), + new String[] { Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE }, + Events.DIRTY + "!=0 AND " + Events.ORIGINAL_ID + " IS NOT NULL", null, null); + while (cursor != null && cursor.moveToNext()) { + Constants.log.debug("Found dirty exception, increasing SEQUENCE to re-schedule"); + long id = cursor.getLong(0), // can't be null (by definition) + originalID = cursor.getLong(1); // can't be null (by query) + int sequence = cursor.isNull(2) ? 0 : cursor.getInt(2); + + BatchOperation batch = new BatchOperation(provider); + // original event to DIRTY + batch.enqueue(ContentProviderOperation.newUpdate( + syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) + .withValue(Events.DIRTY, DIRTY_DONT_INCREASE_SEQUENCE) + .build()); + // increase SEQUENCE and set DIRTY to 0 + batch.enqueue(ContentProviderOperation.newUpdate( + syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))) + .withValue(LocalEvent.COLUMN_SEQUENCE, sequence + 1) + .withValue(Events.DIRTY, 0) + .build()); + batch.commit(); + } + } catch (RemoteException e) { + throw new CalendarStorageException("Couldn't process locally modified exception", e); + } + } + public static class Factory implements AndroidCalendarFactory { public static final Factory INSTANCE = new Factory(); diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java b/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java index 37c7de40..b165c294 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java @@ -10,6 +10,8 @@ package at.bitfire.davdroid.resource; import android.provider.ContactsContract; +import java.io.FileNotFoundException; + import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.vcard4android.ContactsStorageException; @@ -17,7 +19,7 @@ public interface LocalCollection { LocalResource[] getDeleted() throws CalendarStorageException, ContactsStorageException; LocalResource[] getWithoutFileName() throws CalendarStorageException, ContactsStorageException; - LocalResource[] getDirty() throws CalendarStorageException, ContactsStorageException; + LocalResource[] getDirty() throws CalendarStorageException, ContactsStorageException, FileNotFoundException; LocalResource[] getAll() throws CalendarStorageException, ContactsStorageException; diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalContact.java b/app/src/main/java/at/bitfire/davdroid/resource/LocalContact.java index 437f3484..22c959bc 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalContact.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalContact.java @@ -22,7 +22,7 @@ import ezvcard.Ezvcard; public class LocalContact extends AndroidContact implements LocalResource { static { - Contact.productID = "+//IDN bitfire.at//DAVdroid/" + BuildConfig.VERSION_NAME + " ez-vcard/" + Ezvcard.VERSION; + Contact.productID = "+//IDN bitfire.at//DAVdroid/" + BuildConfig.VERSION_NAME + "vcard4android ez-vcard/" + Ezvcard.VERSION; } protected LocalContact(AndroidAddressBook addressBook, long id, String fileName, String eTag) { diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalEvent.java b/app/src/main/java/at/bitfire/davdroid/resource/LocalEvent.java index 7f75cb8e..fa987ba1 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalEvent.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalEvent.java @@ -10,37 +10,46 @@ package at.bitfire.davdroid.resource; import android.content.ContentProviderOperation; import android.content.ContentValues; -import android.net.Uri; import android.os.RemoteException; import android.provider.CalendarContract; +import android.provider.CalendarContract.Events; +import net.fortuna.ical4j.model.property.ProdId; + +import at.bitfire.davdroid.BuildConfig; import at.bitfire.ical4android.AndroidCalendar; import at.bitfire.ical4android.AndroidEvent; import at.bitfire.ical4android.AndroidEventFactory; import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.ical4android.Event; import lombok.Getter; +import lombok.NonNull; import lombok.Setter; public class LocalEvent extends AndroidEvent implements LocalResource { + static { + Event.prodId = new ProdId("+//IDN bitfire.at//DAVdroid/" + BuildConfig.VERSION_NAME + " ical4android ical4j/2.x"); + } - static final String COLUMN_FILENAME = CalendarContract.Events.SYNC_DATA1, - COLUMN_ETAG = CalendarContract.Events.SYNC_DATA2, - COLUMN_UID = CalendarContract.Events.UID_2445; + static final String COLUMN_ETAG = CalendarContract.Events.SYNC_DATA1, + COLUMN_UID = CalendarContract.Events.UID_2445, + COLUMN_SEQUENCE = CalendarContract.Events.SYNC_DATA2; @Getter protected String fileName; @Getter @Setter protected String eTag; - public LocalEvent(AndroidCalendar calendar, Event event, String fileName, String eTag) { + public LocalEvent(@NonNull AndroidCalendar calendar, Event event, String fileName, String eTag) { super(calendar, event); this.fileName = fileName; this.eTag = eTag; } - protected LocalEvent(AndroidCalendar calendar, long id, ContentValues baseInfo) { + protected LocalEvent(@NonNull AndroidCalendar calendar, long id, ContentValues baseInfo) { super(calendar, id, baseInfo); - fileName = baseInfo.getAsString(COLUMN_FILENAME); - eTag = baseInfo.getAsString(COLUMN_ETAG); + if (baseInfo != null) { + fileName = baseInfo.getAsString(Events._SYNC_ID); + eTag = baseInfo.getAsString(COLUMN_ETAG); + } } @@ -49,17 +58,31 @@ public class LocalEvent extends AndroidEvent implements LocalResource { @Override protected void populateEvent(ContentValues values) { super.populateEvent(values); - fileName = values.getAsString(COLUMN_FILENAME); + fileName = values.getAsString(Events._SYNC_ID); eTag = values.getAsString(COLUMN_ETAG); event.uid = values.getAsString(COLUMN_UID); + + if (values.containsKey(COLUMN_SEQUENCE)) + event.sequence = values.getAsInteger(COLUMN_SEQUENCE); } @Override protected void buildEvent(Event recurrence, ContentProviderOperation.Builder builder) { super.buildEvent(recurrence, builder); - builder .withValue(COLUMN_FILENAME, fileName) - .withValue(COLUMN_ETAG, eTag) - .withValue(COLUMN_UID, event.uid); + + boolean buildException = recurrence != null; + Event eventToBuild = buildException ? recurrence : event; + + builder .withValue(COLUMN_UID, event.uid) + .withValue(COLUMN_SEQUENCE, eventToBuild.sequence) + .withValue(CalendarContract.Events.DIRTY, 0) + .withValue(CalendarContract.Events.DELETED, 0); + + if (buildException) + builder.withValue(Events.ORIGINAL_SYNC_ID, fileName); + else + builder .withValue(Events._SYNC_ID, fileName) + .withValue(COLUMN_ETAG, eTag); } @@ -70,7 +93,7 @@ public class LocalEvent extends AndroidEvent implements LocalResource { String newFileName = uid + ".ics"; ContentValues values = new ContentValues(2); - values.put(COLUMN_FILENAME, newFileName); + values.put(Events._SYNC_ID, newFileName); values.put(COLUMN_UID, uid); calendar.provider.update(eventSyncURI(), values, null, null); @@ -89,6 +112,8 @@ public class LocalEvent extends AndroidEvent implements LocalResource { ContentValues values = new ContentValues(2); values.put(CalendarContract.Events.DIRTY, 0); values.put(COLUMN_ETAG, eTag); + if (event != null) + values.put(COLUMN_SEQUENCE, event.sequence); calendar.provider.update(eventSyncURI(), values, null, null); this.eTag = eTag; 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 edc65656..ee03a686 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarSyncManager.java @@ -101,6 +101,13 @@ public class CalendarSyncManager extends SyncManager { localCalendar().update(values); } + @Override + protected void prepareDirty() throws CalendarStorageException, ContactsStorageException { + super.prepareDirty(); + + localCalendar().processDirtyExceptions(); + } + @Override protected RequestBody prepareUpload(LocalResource resource) throws IOException, CalendarStorageException { LocalEvent local = (LocalEvent)resource; 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 32dd8779..2adf4714 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/CalendarsSyncAdapterService.java @@ -16,6 +16,7 @@ import android.content.Intent; import android.content.SyncResult; import android.os.Bundle; import android.os.IBinder; +import android.provider.CalendarContract; import at.bitfire.davdroid.Constants; import at.bitfire.davdroid.resource.LocalCalendar; @@ -52,7 +53,7 @@ public class CalendarsSyncAdapterService extends Service { Constants.log.info("Starting calendar sync (" + authority + ")"); try { - for (LocalCalendar calendar : (LocalCalendar[])LocalCalendar.findAll(account, provider, LocalCalendar.Factory.INSTANCE)) { + for (LocalCalendar calendar : (LocalCalendar[])LocalCalendar.find(account, provider, LocalCalendar.Factory.INSTANCE, CalendarContract.Calendars.SYNC_EVENTS + "!=0", null)) { Constants.log.info("Synchronizing calendar #" + calendar.getId() + ", URL: " + calendar.getName()); CalendarSyncManager syncManager = new CalendarSyncManager(getContext(), account, extras, provider, syncResult, calendar); syncManager.performSync(); 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 c991fca8..3e9d8c03 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/SyncManager.java @@ -24,6 +24,7 @@ import com.squareup.okhttp.HttpUrl; import com.squareup.okhttp.RequestBody; import java.io.IOException; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -34,6 +35,7 @@ import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4android.exception.PreconditionFailedException; +import at.bitfire.dav4android.exception.ServiceUnavailableException; import at.bitfire.dav4android.property.GetCTag; import at.bitfire.dav4android.property.GetETag; import at.bitfire.davdroid.Constants; @@ -50,7 +52,7 @@ abstract public class SyncManager { protected final int SYNC_PHASE_PREPARE = 0, SYNC_PHASE_QUERY_CAPABILITIES = 1, SYNC_PHASE_PROCESS_LOCALLY_DELETED = 2, - SYNC_PHASE_PREPARE_LOCALLY_CREATED = 3, + SYNC_PHASE_PREPARE_DIRTY = 3, SYNC_PHASE_UPLOAD_DIRTY = 4, SYNC_PHASE_CHECK_SYNC_STATE = 5, SYNC_PHASE_LIST_LOCAL = 6, @@ -120,9 +122,9 @@ abstract public class SyncManager { Constants.log.info("Processing locally deleted entries"); processLocallyDeleted(); - syncPhase = SYNC_PHASE_PREPARE_LOCALLY_CREATED; - Constants.log.info("Processing locally created entries"); - processLocallyCreated(); + syncPhase = SYNC_PHASE_PREPARE_DIRTY; + Constants.log.info("Locally preparing dirty entries"); + prepareDirty(); syncPhase = SYNC_PHASE_UPLOAD_DIRTY; Constants.log.info("Uploading dirty entries"); @@ -153,10 +155,18 @@ abstract public class SyncManager { } else Constants.log.info("Remote collection didn't change, skipping remote sync"); - } catch (IOException e) { + } catch (IOException|ServiceUnavailableException e) { Constants.log.error("I/O exception during sync, trying again later", e); syncResult.stats.numIoExceptions++; + if (e instanceof ServiceUnavailableException) { + Date retryAfter = ((ServiceUnavailableException) e).retryAfter; + if (retryAfter != null) { + // how many seconds to wait? getTime() returns ms, so divide by 1000 + syncResult.delayUntil = (retryAfter.getTime() - new Date().getTime()) / 1000; + } + } + } catch(HttpException|DavException e) { Constants.log.error("HTTP/DAV Exception during sync", e); syncResult.stats.numParseExceptions++; @@ -207,7 +217,7 @@ abstract public class SyncManager { try { new DavResource(httpClient, collectionURL.newBuilder().addPathSegment(fileName).build()) .delete(local.getETag()); - } catch (IOException | HttpException e) { + } catch (IOException|HttpException e) { Constants.log.warn("Couldn't delete " + fileName + " from server"); } } else @@ -217,7 +227,7 @@ abstract public class SyncManager { } } - protected void processLocallyCreated() throws CalendarStorageException, ContactsStorageException { + protected void prepareDirty() throws CalendarStorageException, ContactsStorageException { // assign file names and UIDs to new contacts so that we can use the file name as an index for (LocalResource local : localCollection.getWithoutFileName()) { String uuid = UUID.randomUUID().toString(); diff --git a/app/src/main/java/at/bitfire/davdroid/ui/DebugInfoActivity.java b/app/src/main/java/at/bitfire/davdroid/ui/DebugInfoActivity.java index 9c02c54d..962fc39b 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/DebugInfoActivity.java +++ b/app/src/main/java/at/bitfire/davdroid/ui/DebugInfoActivity.java @@ -38,8 +38,6 @@ public class DebugInfoActivity extends Activity { KEY_ACCOUNT = "account", KEY_PHASE = "phase"; - private static final String APP_ID = "at.bitfire.davdroid"; - String report; @Override @@ -49,7 +47,7 @@ public class DebugInfoActivity extends Activity { setContentView(R.layout.debug_info_activity); TextView tvReport = (TextView)findViewById(R.id.text_report); - tvReport.setText(generateReport(getIntent().getExtras())); + tvReport.setText(report = generateReport(getIntent().getExtras())); } @Override @@ -96,7 +94,7 @@ public class DebugInfoActivity extends Activity { try { PackageManager pm = getPackageManager(); - String installedFrom = pm.getInstallerPackageName("at.bitfire.davdroid"); + String installedFrom = pm.getInstallerPackageName(BuildConfig.APPLICATION_ID); if (TextUtils.isEmpty(installedFrom)) installedFrom = "APK (directly)"; else { diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 1252877b..3935b748 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -183,8 +183,8 @@ Vorbereiten der Synchronisierung Abfragen der Server-Fähigkeiten Verarbeiten lokal gelöschter Einträge - Vorbereiten neuer lokaler Einträge - Hochladen neuer/geänderter lokaler Einträge + Vorbereiten neuer/geänderter Einträge + Hochladen neuer/geänderter Einträge Abfragen des Synchronisierungs-Zustands Auflisten lokaler Einträge Auflisten der Server-Einträge diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 75f70cea..16da753b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -198,7 +198,7 @@ preparing synchronization querying capabilities processing locally deleted entries - preparing locally created entries + preparing created/modified entries uploading created/modified entries checking sync state listing local entries diff --git a/ical4android b/ical4android index 4e1131ae..ea504f25 160000 --- a/ical4android +++ b/ical4android @@ -1 +1 @@ -Subproject commit 4e1131ae4607b4220e2d37632fd54a987b633849 +Subproject commit ea504f2512ad5e9a85391797bdbdeb6c92871cdf