Tue, 10 Feb 2015 22:40:00 +0100
Merge https://github.com/gggard/AndroidCaldavSyncAdapater/pull/206/
1 /**
2 * Copyright (c) 2012-2013, Gerald Garcia, David Wiesner, Timo Berger
3 *
4 * This file is part of Andoid Caldav Sync Adapter Free.
5 *
6 * Andoid Caldav Sync Adapter Free is free software: you can redistribute
7 * it and/or modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation, either version 3 of the
9 * License, or at your option any later version.
10 *
11 * Andoid Caldav Sync Adapter Free is distributed in the hope that
12 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
13 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Andoid Caldav Sync Adapter Free.
18 * If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
22 package org.gege.caldavsyncadapter.syncadapter;
24 import android.accounts.Account;
25 import android.accounts.AccountManager;
26 import android.content.AbstractThreadedSyncAdapter;
27 import android.content.ContentProviderClient;
28 import android.content.ContentUris;
29 import android.content.ContentValues;
30 import android.content.Context;
31 import android.content.SyncResult;
32 import android.content.SyncStats;
33 import android.content.pm.PackageManager.NameNotFoundException;
34 import android.database.Cursor;
35 import android.net.Uri;
36 import android.os.Bundle;
37 import android.os.RemoteException;
38 import android.provider.CalendarContract.Attendees;
39 import android.provider.CalendarContract.Calendars;
40 import android.provider.CalendarContract.Events;
41 import android.provider.CalendarContract.Reminders;
42 import android.util.Log;
44 import net.fortuna.ical4j.data.ParserException;
46 import org.apache.http.ParseException;
47 import org.apache.http.client.ClientProtocolException;
48 import org.gege.caldavsyncadapter.Constants;
49 import org.gege.caldavsyncadapter.Event;
50 import org.gege.caldavsyncadapter.android.entities.AndroidEvent;
51 import org.gege.caldavsyncadapter.authenticator.AuthenticatorActivity;
52 import org.gege.caldavsyncadapter.caldav.CaldavFacade;
53 import org.gege.caldavsyncadapter.caldav.CaldavProtocolException;
54 import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent;
55 import org.gege.caldavsyncadapter.caldav.entities.CalendarList;
56 import org.gege.caldavsyncadapter.caldav.entities.DavCalendar;
57 import org.gege.caldavsyncadapter.caldav.entities.DavCalendar.CalendarSource;
58 import org.gege.caldavsyncadapter.syncadapter.notifications.NotificationsHelper;
59 import org.xml.sax.SAXException;
61 import java.io.IOException;
62 import java.net.URI;
63 import java.net.URISyntaxException;
64 import java.util.ArrayList;
66 import javax.xml.parsers.ParserConfigurationException;
68 //import java.net.MalformedURLException;
69 //import java.security.GeneralSecurityException;
71 public class SyncAdapter extends AbstractThreadedSyncAdapter {
73 private static final String TAG = "SyncAdapter";
74 private AccountManager mAccountManager;
75 private String mVersion = "";
76 private int mCountPerformSync = 0;
77 private int mCountSyncCanceled = 0;
78 private int mCountProviderFailed = 0;
80 private int mCountProviderFailedMax = 3;
81 // private Context mContext;
84 /* private static final String[] CALENDAR_PROJECTION = new String[] {
85 Calendars._ID, // 0
86 Calendars.ACCOUNT_NAME, // 1
87 Calendars.CALENDAR_DISPLAY_NAME, // 2
88 Calendars.OWNER_ACCOUNT, // 3
89 Calendar.CTAG // 4
90 };*/
92 /* // The indices for the projection array above.
93 private static final int PROJECTION_ID_INDEX = 0;
94 private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
95 private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
96 private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;
97 */
99 /*
100 private static final String[] EVENT_PROJECTION = new String[] {
101 Events._ID,
102 Events._SYNC_ID,
103 Events.SYNC_DATA1,
104 Events.CALENDAR_ID
105 };
106 */
108 // ignore same CTag
109 //private static final boolean FORCE_SYNCHRONIZE = false;
110 // drop all calendar before synchro
111 //private static final boolean DROP_CALENDAR_EVENTS = false;
113 public SyncAdapter(Context context, boolean autoInitialize) {
114 super(context, autoInitialize);
115 //android.os.Debug.waitForDebugger();
116 mAccountManager = AccountManager.get(context);
117 try {
118 mVersion = context.getPackageManager()
119 .getPackageInfo(context.getPackageName(), 0).versionName;
120 } catch (NameNotFoundException e) {
121 e.printStackTrace();
122 }
123 // mContext = context;
124 }
126 @Override
127 public void onPerformSync(Account account, Bundle extras, String authority,
128 ContentProviderClient provider, SyncResult syncResult) {
129 boolean bolError = false;
131 String url = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_URL_KEY);
132 String trust = mAccountManager.getUserData(account, Constants.USER_DATA_TRUST_ALL_KEY);
133 this.mCountPerformSync += 1;
134 Log.v(TAG, "onPerformSync() count:" + String.valueOf(this.mCountPerformSync) + " on " + account.name + " with URL " + url);
136 CalendarList serverCalList;
138 CalendarList androidCalList = new CalendarList(account, provider, CalendarSource.Android, url);
139 androidCalList.readCalendarFromClient();
140 ArrayList<Uri> notifyList = new ArrayList<Uri>();
142 try {
143 String Username = "";
144 String UserDataVersion = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_VERSION);
145 if (UserDataVersion == null) {
146 Username = account.name;
147 } else {
148 Username = mAccountManager.getUserData(account, AuthenticatorActivity.USER_DATA_USERNAME);
149 }
151 CaldavFacade facade = new CaldavFacade(Username, mAccountManager.getPassword(account), url, trust);
152 facade.setAccount(account);
153 facade.setProvider(provider);
154 facade.setVersion(mVersion);
155 serverCalList = facade.getCalendarList(this.getContext());
156 //String davProperties = facade.getLastDav();
157 Log.i(TAG, String.valueOf(androidCalList.getCalendarList()
158 .size()) + " calendars found at android");
160 for (DavCalendar serverCalendar : serverCalList.getCalendarList()) {
161 Log.i(TAG, "Detected calendar name=" + serverCalendar.getCalendarDisplayName() + " URI=" + serverCalendar
162 .getURI());
164 Uri androidCalendarUri = serverCalendar.checkAndroidCalendarList(androidCalList, this
165 .getContext());
167 // check if the adapter was able to get an existing calendar or create a new one
168 if (androidCalendarUri != null) {
169 // the provider seems to work correct, reset the counter
170 mCountProviderFailed = 0;
171 DavCalendar androidCalendar = androidCalList.getCalendarByAndroidUri(androidCalendarUri);
173 //if ((FORCE_SYNCHRONIZE) || (androidCalendar.getcTag() == null) || (!androidCalendar.getcTag().equals(serverCalendar.getcTag()))) {
174 if ((androidCalendar.getcTag() == null) || (!androidCalendar.getcTag()
175 .equals(serverCalendar.getcTag()))) {
176 Log.d(TAG, "CTag has changed, something to synchronise");
177 if (serverCalendar.readCalendarEvents(facade)) {
178 this.synchroniseEvents(androidCalendar, serverCalendar, syncResult.stats, notifyList);
180 Log.d(TAG, "Updating stored CTag");
181 //serverCalendar.updateAndroidCalendar(androidCalendarUri, Calendar.CTAG, serverCalendar.getcTag());
182 androidCalendar.setCTag(serverCalendar.getcTag(), true);
183 } else {
184 Log.d(TAG, "unable to read events from server calendar");
185 }
186 } else {
187 Log.d(TAG, "CTag has not changed, nothing to do");
189 /* this is unnecessary. "SkippedEntries" are:
190 * Counter for tracking how many entries, either from the server or the local store,
191 * were ignored during the sync operation. This could happen if the SyncAdapter detected
192 * some unparsable data but decided to skip it and move on rather than failing immediately.
193 */
195 /*long CalendarID = ContentUris.parseId(androidCalendarUri);
196 String selection = "(" + Events.CALENDAR_ID + " = ?)";
197 String[] selectionArgs = new String[] {String.valueOf(CalendarID)};
198 Cursor countCursor = provider.query(Events.CONTENT_URI, new String[] {"count(*) AS count"},
199 selection,
200 selectionArgs,
201 null);
203 countCursor.moveToFirst();
204 int count = countCursor.getInt(0);
205 syncResult.stats.numSkippedEntries += count;
206 countCursor.close();*/
208 }
210 this.checkDirtyAndroidEvents(provider, account, androidCalendarUri, facade, serverCalendar
211 .getURI(), syncResult.stats, notifyList);
212 } else {
213 // this happens if the data provider failes to get an existing or create a new calendar
214 mCountProviderFailed += 1;
215 Log.e(TAG, "failed to get an existing or create a new calendar");
216 syncResult.stats.numIoExceptions += 1;
217 if (mCountProviderFailed >= mCountProviderFailedMax) {
218 // see issue #96
219 NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (provider failed)", "are you using CyanogenMod in Incognito Mode?");
220 } else {
221 NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (provider failed)", "the provider failed to get an existing or create a new calendar");
222 }
223 bolError = true;
224 }
225 }
227 if (!bolError) {
228 // check whether a calendar is not synced -> delete it at android
229 androidCalList.deleteCalendarOnClientSideOnly(this.getContext());
230 }
232 // notify the ContentResolver
233 for (Uri uri : androidCalList.getNotifyList()) {
234 this.getContext().getContentResolver().notifyChange(uri, null);
235 }
236 for (Uri uri : serverCalList.getNotifyList()) {
237 this.getContext().getContentResolver().notifyChange(uri, null);
238 }
239 for (Uri uri : notifyList) {
240 this.getContext().getContentResolver().notifyChange(uri, null);
241 }
243 //Log.i(TAG,"Statistiks for Calendar: " + serverCalendar.getURI().toString());
244 //Log.i(TAG,"Statistiks for AndroidCalendar: " + androidCalendar.getAndroidCalendarUri().toString());
245 Log.i(TAG, "Entries: " + String.valueOf(syncResult.stats.numEntries));
246 Log.i(TAG, "Rows inserted: " + String.valueOf(syncResult.stats.numInserts));
247 Log.i(TAG, "Rows updated: " + String.valueOf(syncResult.stats.numUpdates));
248 Log.i(TAG, "Rows deleted: " + String.valueOf(syncResult.stats.numDeletes));
249 Log.i(TAG, "Rows skipped: " + String.valueOf(syncResult.stats.numSkippedEntries));
250 Log.i(TAG, "Io Exceptions: " + String.valueOf(syncResult.stats.numIoExceptions));
251 Log.i(TAG, "Parse Exceptions: " + String.valueOf(syncResult.stats.numParseExceptions));
252 Log.i(TAG, "Auth Exceptions: " + String.valueOf(syncResult.stats.numAuthExceptions));
253 Log.i(TAG, "Conflict Detected Exceptions: " + String.valueOf(syncResult.stats.numConflictDetectedExceptions));
255 /*} catch (final AuthenticatorException e) {
256 syncResult.stats.numParseExceptions++;
257 Log.e(TAG, "AuthenticatorException", e);*/
258 /*} catch (final OperationCanceledException e) {
259 Log.e(TAG, "OperationCanceledExcetpion", e);*/
260 } catch (final IOException e) {
261 Log.e(TAG, "IOException", e);
262 syncResult.stats.numIoExceptions++;
263 NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (IO)", e.getMessage());
264 //NotificationsHelper.getCurrentSyncLog().addException(e);
265 /*} catch (final AuthenticationException e) {
266 //mAccountManager.invalidateAuthToken(Constants.ACCOUNT_TYPE, authtoken);
267 syncResult.stats.numAuthExceptions++;
268 Log.e(TAG, "AuthenticationException", e);*/
269 } catch (final ParseException e) {
270 syncResult.stats.numParseExceptions++;
271 Log.e(TAG, "ParseException", e);
272 NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (parsing)", e
273 .getMessage());
274 //NotificationsHelper.getCurrentSyncLog().addException(e);
275 /*} catch (final JSONException e) {
276 syncResult.stats.numParseExceptions++;
277 Log.e(TAG, "JSONException", e);*/
278 } catch (Exception e) {
279 Log.e(TAG, "Updating calendar exception " + e.getClass().getName(), e);
280 syncResult.stats.numParseExceptions++;
281 NotificationsHelper.signalSyncErrors(this.getContext(), "Caldav sync error (general)", e
282 .getMessage());
283 //NotificationsHelper.getCurrentSyncLog().addException(e);
284 //throw new RuntimeException(e);
285 }
286 }
288 public void onSyncCanceled() {
289 //TODO: implement SyncCanceled
290 this.mCountSyncCanceled += 1;
291 Log.v(TAG, "onSyncCanceled() count:" + String.valueOf(this.mCountSyncCanceled));
292 }
295 /**
296 * both calender event and android event have been found.
297 * server wins always at the moment.
298 *
299 * @param androidCalendar
300 * @param serverCalendar
301 * @param stats
302 * @param notifyList
303 * @throws ClientProtocolException
304 * @throws URISyntaxException
305 * @throws IOException
306 * @throws ParserConfigurationException
307 * @throws SAXException
308 * @throws RemoteException
309 * @throws CaldavProtocolException
310 * @throws ParserException
311 * @see SyncAdapter#updateAndroidEvent(ContentProviderClient, Account, AndroidEvent, CalendarEvent)
312 * @see SyncAdapter#tagAndroidEvent(ContentProviderClient, Account, AndroidEvent)
313 * @see SyncAdapter#untagAndroidEvents(ContentProviderClient, Account, Uri)
314 * @see SyncAdapter#deleteUntaggedEvents(ContentProviderClient, Account, Uri)
315 */
316 private void synchroniseEvents(
317 DavCalendar androidCalendar,
318 DavCalendar serverCalendar,
319 SyncStats stats,
320 ArrayList<Uri> notifyList
321 ) throws ClientProtocolException, URISyntaxException, IOException, ParserConfigurationException, SAXException, RemoteException, CaldavProtocolException, ParserException {
323 /*if (DROP_CALENDAR_EVENTS) {
324 dropAllEvents(account, provider, androidCalendar.getAndroidCalendarUri());
325 }*/
327 int rowInsert = 0;
328 int rowUpdate = 0;
329 int rowTag = 0;
330 int rowDelete = 0;
331 int rowUntag = 0;
332 int rowSkip = 0;
334 for (CalendarEvent calendarEvent : serverCalendar.getCalendarEvents()) {
335 try {
336 AndroidEvent androidEvent = calendarEvent.getAndroidEvent(androidCalendar);
338 Log.i(TAG, "Event " + calendarEvent.getUri()
339 .toString() + " androidUri=" + androidEvent);
341 if (androidEvent == null) {
342 /* new android event */
343 if (calendarEvent.createAndroidEvent(androidCalendar)) {
344 rowInsert += 1;
345 androidEvent = calendarEvent.getAndroidEvent(androidCalendar);
346 notifyList.add(androidEvent.getUri());
347 } else {
348 rowSkip += 1;
349 }
350 } else {
351 /* the android exists */
352 String androidETag = androidEvent.getETag();
353 if (androidETag == null)
354 androidETag = "";
355 Log.d(TAG, "Event compare: " + androidETag + " <> " + calendarEvent.getETag()
356 .toString());
357 if ((androidEvent.getETag() == null) || (!androidETag.equals(calendarEvent.getETag()))) {
358 /* the android event is getting updated */
359 if (calendarEvent.updateAndroidEvent(androidEvent)) {
360 rowUpdate += 1;
361 notifyList.add(androidEvent.getUri());
362 } else {
363 rowSkip += 1;
364 }
365 }
366 }
367 if (androidEvent != null)
368 //if (androidEvent.tagAndroidEvent())
369 if (androidCalendar.tagAndroidEvent(androidEvent))
370 rowTag += 1;
373 } catch (ParserException ex) {
374 Log.e(TAG, "Parser exception", ex);
375 stats.numParseExceptions++;
377 NotificationsHelper.signalSyncErrors(getContext(), "Caldav sync error (parsing)", ex
378 .getMessage());
379 //NotificationsHelper.getCurrentSyncLog().addException(ex);
380 } catch (CaldavProtocolException ex) {
381 Log.e(TAG, "Caldav exception", ex);
382 stats.numParseExceptions++;
384 NotificationsHelper.signalSyncErrors(getContext(), "Caldav sync error (caldav)", ex.getMessage());
385 //NotificationsHelper.getCurrentSyncLog().addException(ex);
386 }
387 }
389 rowDelete = androidCalendar.deleteUntaggedEvents();
390 rowUntag = androidCalendar.untagAndroidEvents();
392 /*Log.i(TAG,"Statistiks for Calendar: " + serverCalendar.getURI().toString());
393 Log.i(TAG,"Statistiks for AndroidCalendar: " + androidCalendar.getAndroidCalendarUri().toString());
394 Log.i(TAG,"Rows inserted: " + String.valueOf(rowInsert));
395 Log.i(TAG,"Rows updated: " + String.valueOf(rowUpdate));
396 Log.i(TAG,"Rows deleted: " + String.valueOf(rowDelete));
397 Log.i(TAG,"Rows skipped: " + String.valueOf(rowSkip));*/
398 Log.i(TAG, "Rows tagged: " + String.valueOf(rowTag));
399 Log.i(TAG, "Rows untagged: " + String.valueOf(rowUntag));
401 stats.numInserts += rowInsert;
402 stats.numUpdates += rowUpdate;
403 stats.numDeletes += rowDelete;
404 stats.numSkippedEntries += rowSkip;
405 stats.numEntries += rowInsert + rowUpdate + rowDelete;
407 }
409 /**
410 * checks the android events for the dirty flag.
411 * the flag is set by android when the event has been changed.
412 * the dirty flag is removed when an android event has been updated from calendar event
413 *
414 * @param provider
415 * @param account
416 * @param calendarUri
417 * @param facade
418 * @param caldavCalendarUri
419 * @param stats
420 * @param notifyList
421 * @return count of dirty events
422 */
423 private int checkDirtyAndroidEvents(
424 ContentProviderClient provider,
425 Account account,
426 Uri calendarUri,
427 CaldavFacade facade,
428 URI caldavCalendarUri,
429 SyncStats stats,
430 ArrayList<Uri> notifyList
431 ) {
432 Cursor curEvent = null;
433 Cursor curAttendee = null;
434 Cursor curReminder = null;
435 Long EventID;
436 Long CalendarID;
437 AndroidEvent androidEvent = null;
438 int rowDirty = 0;
439 int rowInsert = 0;
440 int rowUpdate = 0;
441 int rowDelete = 0;
443 try {
444 CalendarID = ContentUris.parseId(calendarUri);
445 String selection = "(" + Events.DIRTY + " = ?) AND (" + Events.CALENDAR_ID + " = ?)";
446 String[] selectionArgs = new String[]{"1", CalendarID.toString()};
447 curEvent = provider.query(Events.CONTENT_URI, null, selection, selectionArgs, null);
449 while (curEvent.moveToNext()) {
450 EventID = curEvent.getLong(curEvent.getColumnIndex(Events._ID));
451 Uri returnedUri = ContentUris.withAppendedId(Events.CONTENT_URI, EventID);
453 //androidEvent = new AndroidEvent(account, provider, returnedUri, calendarUri);
454 androidEvent = new AndroidEvent(returnedUri, calendarUri);
455 androidEvent.readContentValues(curEvent);
457 selection = "(" + Attendees.EVENT_ID + " = ?)";
458 selectionArgs = new String[]{String.valueOf(EventID)};
459 curAttendee = provider.query(Attendees.CONTENT_URI, null, selection, selectionArgs, null);
460 selection = "(" + Reminders.EVENT_ID + " = ?)";
461 selectionArgs = new String[]{String.valueOf(EventID)};
462 curReminder = provider.query(Reminders.CONTENT_URI, null, selection, selectionArgs, null);
463 androidEvent.readAttendees(curAttendee);
464 androidEvent.readReminder(curReminder);
465 curAttendee.close();
466 curReminder.close();
468 String SyncID = androidEvent.ContentValues.getAsString(Events._SYNC_ID);
470 boolean Deleted = false;
471 int intDeleted = 0;
472 intDeleted = curEvent.getInt(curEvent.getColumnIndex(Events.DELETED));
473 Deleted = (intDeleted == 1);
475 if (SyncID == null) {
476 // new Android event
477 String newGUID = java.util.UUID.randomUUID().toString() + "-caldavsyncadapter";
478 String calendarPath = caldavCalendarUri.getPath();
479 if (!calendarPath.endsWith("/"))
480 calendarPath += "/";
482 SyncID = calendarPath + newGUID + ".ics";
484 androidEvent.createIcs(newGUID);
486 if (facade.createEvent(URI.create(SyncID), androidEvent.getIcsEvent()
487 .toString())) {
488 //HINT: bugfix for google calendar replace("@", "%40")
489 if (SyncID.contains("@"))
490 SyncID = SyncID.replace("@", "%40");
491 ContentValues values = new ContentValues();
492 values.put(Events._SYNC_ID, SyncID);
494 //google doesn't send the etag after creation
495 //HINT: my SabreDAV send always the same etag after putting a new event
496 //String LastETag = facade.getLastETag();
497 //if (!LastETag.equals("")) {
498 // values.put(Event.ETAG, LastETag);
499 //} else {
500 //so get the etag with a new REPORT
501 CalendarEvent calendarEvent = new CalendarEvent(account, provider);
502 calendarEvent.calendarURL = caldavCalendarUri.toURL();
503 URI SyncURI = new URI(SyncID);
504 calendarEvent.setUri(SyncURI);
505 CaldavFacade.getEvent(calendarEvent);
506 values.put(Event.ETAG, calendarEvent.getETag());
507 //}
508 values.put(Event.UID, newGUID);
509 values.put(Events.DIRTY, 0);
510 values.put(Event.RAWDATA, androidEvent.getIcsEvent().toString());
512 int rowCount = provider.update(asSyncAdapter(androidEvent.getUri(), account.name, account.type), values, null, null);
513 if (rowCount == 1) {
514 rowInsert += 1;
515 notifyList.add(androidEvent.getUri());
516 }
517 }
518 } else if (Deleted) {
519 // deleted Android event
520 if (facade.deleteEvent(URI.create(SyncID), androidEvent.getETag())) {
521 String mSelectionClause = "(" + Events._ID + "= ?)";
522 String[] mSelectionArgs = {String.valueOf(EventID)};
524 int countDeleted = provider.delete(asSyncAdapter(Events.CONTENT_URI, account.name, account.type), mSelectionClause, mSelectionArgs);
526 if (countDeleted == 1) {
527 rowDelete += 1;
528 notifyList.add(androidEvent.getUri());
529 }
530 }
531 } else {
532 //update the android event to the server
533 String uid = androidEvent.getUID();
534 if ((uid == null) || (uid.equals(""))) {
535 //COMPAT: this is needed because in the past, the UID was not stored in the android event
536 CalendarEvent calendarEvent = new CalendarEvent(account, provider);
537 URI syncURI = new URI(SyncID);
538 calendarEvent.setUri(syncURI);
539 calendarEvent.calendarURL = caldavCalendarUri.toURL();
540 if (calendarEvent.fetchBody()) {
541 calendarEvent.readContentValues();
542 uid = calendarEvent.getUID();
543 }
544 }
545 if (uid != null) {
546 androidEvent.createIcs(uid);
548 if (facade.updateEvent(URI.create(SyncID), androidEvent.getIcsEvent()
549 .toString(), androidEvent.getETag())) {
550 selection = "(" + Events._ID + "= ?)";
551 selectionArgs = new String[]{EventID.toString()};
552 androidEvent.ContentValues.put(Events.DIRTY, 0);
554 //google doesn't send the etag after update
555 String LastETag = facade.getLastETag();
556 if (!LastETag.equals("")) {
557 androidEvent.ContentValues.put(Event.ETAG, LastETag);
558 } else {
559 //so get the etag with a new REPORT
560 CalendarEvent calendarEvent = new CalendarEvent(account, provider);
561 calendarEvent.calendarURL = caldavCalendarUri.toURL();
562 URI SyncURI = new URI(SyncID);
563 calendarEvent.setUri(SyncURI);
564 CaldavFacade.getEvent(calendarEvent);
565 androidEvent.ContentValues.put(Event.ETAG, calendarEvent.getETag());
566 }
567 androidEvent.ContentValues.put(Event.RAWDATA, androidEvent.getIcsEvent()
568 .toString());
569 int RowCount = provider.update(asSyncAdapter(androidEvent.getUri(), account.name, account.type), androidEvent.ContentValues, null, null);
571 if (RowCount == 1) {
572 rowUpdate += 1;
573 notifyList.add(androidEvent.getUri());
574 }
575 } else {
576 rowDirty += 1;
577 }
578 } else {
579 rowDirty += 1;
580 }
581 }
582 }
583 curEvent.close();
585 /*if ((rowInsert > 0) || (rowUpdate > 0) || (rowDelete > 0) || (rowDirty > 0)) {
586 Log.i(TAG,"Android Rows inserted: " + String.valueOf(rowInsert));
587 Log.i(TAG,"Android Rows updated: " + String.valueOf(rowUpdate));
588 Log.i(TAG,"Android Rows deleted: " + String.valueOf(rowDelete));
589 Log.i(TAG,"Android Rows dirty: " + String.valueOf(rowDirty));
590 }*/
592 stats.numInserts += rowInsert;
593 stats.numUpdates += rowUpdate;
594 stats.numDeletes += rowDelete;
595 stats.numSkippedEntries += rowDirty;
596 stats.numEntries += rowInsert + rowUpdate + rowDelete;
597 } catch (RemoteException e) {
598 e.printStackTrace();
599 } catch (URISyntaxException e) {
600 // TODO Automatisch generierter Erfassungsblock
601 e.printStackTrace();
602 } catch (ClientProtocolException e) {
603 // TODO Automatisch generierter Erfassungsblock
604 e.printStackTrace();
605 } catch (IOException e) {
606 // TODO Automatisch generierter Erfassungsblock
607 e.printStackTrace();
608 } catch (CaldavProtocolException e) {
609 // TODO Automatisch generierter Erfassungsblock
610 e.printStackTrace();
611 } catch (ParserException e) {
612 // TODO Automatisch generierter Erfassungsblock
613 e.printStackTrace();
614 }
616 return rowDirty;
617 }
619 /* private Account UpgradeAccount(Account OldAccount) {
620 String Username = OldAccount.name;
621 String Type = OldAccount.type;
622 String Password = this.mAccountManager.getPassword(OldAccount);
623 String Url = this.mAccountManager.getUserData(OldAccount, AuthenticatorActivity.USER_DATA_URL_KEY);
625 Account NewAccount = new Account(Username + AuthenticatorActivity.ACCOUNT_NAME_SPLITTER + Url, Type);
626 if (this.mAccountManager.addAccountExplicitly(NewAccount, Password, null)) {
627 this.mAccountManager.setUserData(NewAccount, AuthenticatorActivity.USER_DATA_URL_KEY, Url);
628 this.mAccountManager.setUserData(NewAccount, AuthenticatorActivity.USER_DATA_USERNAME, Username);
629 }
630 this.mAccountManager.removeAccount(OldAccount, null, null);
632 return NewAccount;
633 }*/
635 /* private void dropAllEvents(Account account, ContentProviderClient provider, Uri calendarUri) throws RemoteException {
637 Log.i(TAG, "Deleting all calendar events for "+calendarUri);
639 String selection = "(" + Events.CALENDAR_ID + " = ?)";
640 String[] selectionArgs = new String[] {Long.toString(ContentUris.parseId(calendarUri))};
642 provider.delete(asSyncAdapter(Events.CONTENT_URI, account.name, account.type),
643 selection, selectionArgs);
645 }*/
647 private static Uri asSyncAdapter(Uri uri, String account, String accountType) {
648 return uri.buildUpon()
649 .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER, "true")
650 .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
651 .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
652 }
654 }