mirror of
https://github.com/etesync/android
synced 2024-12-26 08:28:17 +00:00
Process recurring events, exceptions etc.
This commit is contained in:
parent
0c819c842b
commit
419d732195
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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<LocalResource> 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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -183,8 +183,8 @@
|
||||
<item>Vorbereiten der Synchronisierung</item>
|
||||
<item>Abfragen der Server-Fähigkeiten</item>
|
||||
<item>Verarbeiten lokal gelöschter Einträge</item>
|
||||
<item>Vorbereiten neuer lokaler Einträge</item>
|
||||
<item>Hochladen neuer/geänderter lokaler Einträge</item>
|
||||
<item>Vorbereiten neuer/geänderter Einträge</item>
|
||||
<item>Hochladen neuer/geänderter Einträge</item>
|
||||
<item>Abfragen des Synchronisierungs-Zustands</item>
|
||||
<item>Auflisten lokaler Einträge</item>
|
||||
<item>Auflisten der Server-Einträge</item>
|
||||
|
@ -198,7 +198,7 @@
|
||||
<item>preparing synchronization</item>
|
||||
<item>querying capabilities</item>
|
||||
<item>processing locally deleted entries</item>
|
||||
<item>preparing locally created entries</item>
|
||||
<item>preparing created/modified entries</item>
|
||||
<item>uploading created/modified entries</item>
|
||||
<item>checking sync state</item>
|
||||
<item>listing local entries</item>
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 4e1131ae4607b4220e2d37632fd54a987b633849
|
||||
Subproject commit ea504f2512ad5e9a85391797bdbdeb6c92871cdf
|
Loading…
Reference in New Issue
Block a user