1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/org/gege/caldavsyncadapter/caldav/entities/CalendarEvent.java Tue Feb 10 18:12:00 2015 +0100 1.3 @@ -0,0 +1,1068 @@ 1.4 +/** 1.5 + * Copyright (c) 2012-2013, Gerald Garcia, Timo Berger 1.6 + * 1.7 + * This file is part of Andoid Caldav Sync Adapter Free. 1.8 + * 1.9 + * Andoid Caldav Sync Adapter Free is free software: you can redistribute 1.10 + * it and/or modify it under the terms of the GNU General Public License 1.11 + * as published by the Free Software Foundation, either version 3 of the 1.12 + * License, or at your option any later version. 1.13 + * 1.14 + * Andoid Caldav Sync Adapter Free is distributed in the hope that 1.15 + * it will be useful, but WITHOUT ANY WARRANTY; without even the implied 1.16 + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.17 + * GNU General Public License for more details. 1.18 + * 1.19 + * You should have received a copy of the GNU General Public License 1.20 + * along with Andoid Caldav Sync Adapter Free. 1.21 + * If not, see <http://www.gnu.org/licenses/>. 1.22 + * 1.23 + */ 1.24 + 1.25 +package org.gege.caldavsyncadapter.caldav.entities; 1.26 + 1.27 +import java.io.IOException; 1.28 +import java.io.StringReader; 1.29 +import java.io.UnsupportedEncodingException; 1.30 +import java.net.URI; 1.31 +import java.net.URL; 1.32 +import java.net.URLDecoder; 1.33 +import java.text.ParseException; 1.34 +import java.util.ArrayList; 1.35 + 1.36 +import javax.xml.parsers.ParserConfigurationException; 1.37 +import javax.xml.parsers.SAXParser; 1.38 +import javax.xml.parsers.SAXParserFactory; 1.39 + 1.40 +import net.fortuna.ical4j.data.CalendarBuilder; 1.41 +import net.fortuna.ical4j.data.ParserException; 1.42 +import net.fortuna.ical4j.model.Calendar; 1.43 +import net.fortuna.ical4j.model.Component; 1.44 +import net.fortuna.ical4j.model.ComponentList; 1.45 +import net.fortuna.ical4j.model.DateTime; 1.46 +import net.fortuna.ical4j.model.Dur; 1.47 +import net.fortuna.ical4j.model.Parameter; 1.48 +import net.fortuna.ical4j.model.ParameterList; 1.49 +import net.fortuna.ical4j.model.Property; 1.50 +import net.fortuna.ical4j.model.PropertyList; 1.51 +import net.fortuna.ical4j.model.TimeZone; 1.52 +import net.fortuna.ical4j.model.component.VEvent; 1.53 +import net.fortuna.ical4j.model.component.VTimeZone; 1.54 +import net.fortuna.ical4j.model.parameter.Cn; 1.55 +import net.fortuna.ical4j.model.parameter.CuType; 1.56 +import net.fortuna.ical4j.model.parameter.PartStat; 1.57 +import net.fortuna.ical4j.model.parameter.Role; 1.58 +import net.fortuna.ical4j.model.property.Clazz; 1.59 +import net.fortuna.ical4j.model.property.Status; 1.60 +import net.fortuna.ical4j.util.CompatibilityHints; 1.61 + 1.62 +import org.apache.http.client.ClientProtocolException; 1.63 +import org.gege.caldavsyncadapter.Event; 1.64 +import org.gege.caldavsyncadapter.android.entities.AndroidEvent; 1.65 +import org.gege.caldavsyncadapter.caldav.CaldavFacade; 1.66 +import org.gege.caldavsyncadapter.caldav.CaldavProtocolException; 1.67 +import org.gege.caldavsyncadapter.caldav.xml.MultiStatusHandler; 1.68 +import org.gege.caldavsyncadapter.caldav.xml.sax.MultiStatus; 1.69 +import org.gege.caldavsyncadapter.caldav.xml.sax.Prop; 1.70 +import org.gege.caldavsyncadapter.caldav.xml.sax.PropStat; 1.71 +import org.gege.caldavsyncadapter.caldav.xml.sax.Response; 1.72 +import org.gege.caldavsyncadapter.syncadapter.SyncAdapter; 1.73 +import org.xml.sax.InputSource; 1.74 +import org.xml.sax.SAXException; 1.75 +import org.xml.sax.XMLReader; 1.76 + 1.77 +import android.accounts.Account; 1.78 +import android.content.ContentProviderClient; 1.79 +import android.content.ContentUris; 1.80 +import android.content.ContentValues; 1.81 +import android.content.SyncStats; 1.82 +import android.database.Cursor; 1.83 +import android.net.Uri; 1.84 +import android.os.RemoteException; 1.85 +import android.provider.CalendarContract.Attendees; 1.86 +import android.provider.CalendarContract.Calendars; 1.87 +import android.provider.CalendarContract.Events; 1.88 +import android.provider.CalendarContract.Reminders; 1.89 +import android.util.Log; 1.90 + 1.91 + 1.92 + 1.93 +public class CalendarEvent extends org.gege.caldavsyncadapter.Event { 1.94 + private static final String TAG = "CalendarEvent"; 1.95 + 1.96 + private String stringIcs; 1.97 + 1.98 + private Calendar calendar; 1.99 + 1.100 + private Component calendarComponent; 1.101 + 1.102 + private String eTag; 1.103 + private URI muri; 1.104 + private Uri mAndroidEventUri; 1.105 + public URL calendarURL; 1.106 + 1.107 + private boolean mAllDay = false; 1.108 + private VTimeZone mVTimeZone = null; 1.109 + private TimeZone mTimeZone = null; 1.110 + 1.111 + private String mstrTimeZoneStart = ""; 1.112 + private String mstrTimeZoneEnd = ""; 1.113 + 1.114 + private Account mAccount = null; 1.115 + private ContentProviderClient mProvider = null; 1.116 + 1.117 + public CalendarEvent(Account account, ContentProviderClient provider) { 1.118 + this.mAccount = account; 1.119 + this.mProvider = provider; 1.120 + } 1.121 + 1.122 + public String getETag() { 1.123 + return eTag; 1.124 + } 1.125 + 1.126 + public void setETag(String eTag) { 1.127 + this.eTag = eTag; 1.128 + } 1.129 + 1.130 + public URI getUri() { 1.131 + return muri; 1.132 + } 1.133 + 1.134 + public void setUri(URI uri) { 1.135 + this.muri = uri; 1.136 + } 1.137 + 1.138 + public void setICSasString(String ics) { 1.139 + this.stringIcs = ics; 1.140 + } 1.141 + 1.142 + public boolean setICSasMultiStatus(String stringMultiStatus) { 1.143 + boolean Result = false; 1.144 + String ics = ""; 1.145 + MultiStatus multistatus; 1.146 + ArrayList<Response> responselist; 1.147 + Response response; 1.148 + PropStat propstat; 1.149 + Prop prop; 1.150 + try { 1.151 + SAXParserFactory factory = SAXParserFactory.newInstance(); 1.152 + SAXParser parser = factory.newSAXParser(); 1.153 + XMLReader reader = parser.getXMLReader(); 1.154 + MultiStatusHandler contentHandler = new MultiStatusHandler(); 1.155 + reader.setContentHandler(contentHandler); 1.156 + reader.parse(new InputSource(new StringReader(stringMultiStatus))); 1.157 + 1.158 + multistatus = contentHandler.mMultiStatus; 1.159 + if (multistatus != null) { 1.160 + responselist = multistatus.ResponseList; 1.161 + if (responselist.size() == 1) { 1.162 + response = responselist.get(0); 1.163 + //HINT: bugfix for google calendar, zimbra replace("@", "%40") 1.164 + if (response.href.replace("@", "%40").equals(this.getUri().getRawPath().replace("@", "%40"))) { 1.165 + propstat = response.propstat; 1.166 + if (propstat != null) { 1.167 + if (propstat.status.contains("200 OK")) { 1.168 + prop = propstat.prop; 1.169 + ics = prop.calendardata; 1.170 + this.setETag(prop.getetag); 1.171 + Result = true; 1.172 + } 1.173 + } 1.174 + } 1.175 + } 1.176 + } 1.177 + } catch (ParserConfigurationException e1) { 1.178 + e1.printStackTrace(); 1.179 + } catch (SAXException e1) { 1.180 + e1.printStackTrace(); 1.181 + } catch (IOException e) { 1.182 + e.printStackTrace(); 1.183 + } 1.184 + 1.185 + this.stringIcs = ics; 1.186 + return Result; 1.187 + } 1.188 + 1.189 + /** 1.190 + * sets the Uri of the android event 1.191 + * @param uri 1.192 + * @see org.gege.caldavsyncadapter.syncadapter.SyncAdapter#createAndroidEvent(ContentProviderClient provider, Account account, Uri calendarUri, CalendarEvent calendarEvent) 1.193 + * @see org.gege.caldavsyncadapter.syncadapter.SyncAdapter#updateAndroidEvent(ContentProviderClient provider, Account account, AndroidEvent androidEvent, CalendarEvent calendarEvent) 1.194 + */ 1.195 + public void setAndroidEventUri(Uri uri) { 1.196 + mAndroidEventUri = uri; 1.197 + } 1.198 + 1.199 + /** 1.200 + * gets the Uri of the android event 1.201 + * @return 1.202 + */ 1.203 + public Uri getAndroidEventUri() { 1.204 + return mAndroidEventUri; 1.205 + } 1.206 + 1.207 + 1.208 + /** 1.209 + * reads all ContentValues from the caldav source 1.210 + * @param calendarUri 1.211 + * @return 1.212 + * @see org.gege.caldavsyncadapter.syncadapter.SyncAdapter#createAndroidEvent(ContentProviderClient provider, Account account, Uri calendarUri, CalendarEvent calendarEvent) 1.213 + * @see org.gege.caldavsyncadapter.syncadapter.SyncAdapter#updateAndroidEvent(ContentProviderClient provider, Account account, AndroidEvent androidEvent, CalendarEvent calendarEvent) 1.214 + */ 1.215 + public boolean readContentValues() { 1.216 + this.ContentValues.put(Events.DTSTART, this.getStartTime()); 1.217 + this.ContentValues.put(Events.EVENT_TIMEZONE, this.getTimeZoneStart()); 1.218 + 1.219 + //if (this.getRRule().isEmpty() && this.getRDate().isEmpty()) { 1.220 + if (this.getRRule() == null && this.getRDate() == null) { 1.221 + //if (AllDay.equals(1)) //{ 1.222 + // values.put(Events.ALL_DAY, AllDay); 1.223 + //} else { 1.224 + this.ContentValues.put(Events.DTEND, this.getEndTime()); 1.225 + this.ContentValues.put(Events.EVENT_END_TIMEZONE, this.getTimeZoneEnd()); 1.226 + //} 1.227 + } else { 1.228 + //if (AllDay.equals(1)) 1.229 + // values.put(Events.ALL_DAY, AllDay); 1.230 + this.ContentValues.put(Events.DURATION, this.getDuration()); 1.231 + } 1.232 + int AllDay = this.getAllDay(); 1.233 + this.ContentValues.put(Events.ALL_DAY, AllDay); 1.234 + 1.235 + this.ContentValues.put(Events.TITLE, this.getTitle()); 1.236 + //this.ContentValues.put(Events.CALENDAR_ID, ContentUris.parseId(calendarUri)); 1.237 + this.ContentValues.put(Events._SYNC_ID, this.getUri().toString()); 1.238 + this.ContentValues.put(ETAG, this.getETag()); 1.239 + this.ContentValues.put(Events.DESCRIPTION, this.getDescription()); 1.240 + this.ContentValues.put(Events.EVENT_LOCATION, this.getLocation()); 1.241 + this.ContentValues.put(Events.ACCESS_LEVEL, this.getAccessLevel()); 1.242 + this.ContentValues.put(Events.STATUS, this.getStatus()); 1.243 + this.ContentValues.put(Events.RDATE, this.getRDate()); 1.244 + this.ContentValues.put(Events.RRULE, this.getRRule()); 1.245 + this.ContentValues.put(Events.EXRULE, this.getExRule()); 1.246 + this.ContentValues.put(Events.EXDATE, this.getExDate()); 1.247 + this.ContentValues.put(UID, this.getUid()); 1.248 + this.ContentValues.put(RAWDATA, this.stringIcs); 1.249 + 1.250 + return true; 1.251 + } 1.252 + 1.253 + /** 1.254 + * receives a single event and parses its content 1.255 + * @return success of this function 1.256 + * @see CalendarEvent#parseIcs() 1.257 + * @throws ClientProtocolException 1.258 + * @throws IOException 1.259 + * @throws CaldavProtocolException 1.260 + * @throws ParserException 1.261 + */ 1.262 + public boolean fetchBody() throws ClientProtocolException, IOException, CaldavProtocolException, ParserException { 1.263 + boolean Error = false; 1.264 + 1.265 + //replaced fetchEvent() with getEvent() 1.266 + //CaldavFacade.fetchEvent(this); 1.267 + CaldavFacade.getEvent(this); 1.268 + 1.269 + boolean Parse = this.parseIcs(); 1.270 + if (!Parse) 1.271 + Error = true; 1.272 + 1.273 + return !Error; 1.274 + } 1.275 + 1.276 + public java.util.ArrayList<ContentValues> getReminders() { 1.277 + java.util.ArrayList<ContentValues> Result = new java.util.ArrayList<ContentValues>(); 1.278 + ContentValues Reminder; 1.279 + 1.280 + /* 1.281 + * http://sourceforge.net/tracker/?func=detail&aid=3021704&group_id=107024&atid=646395 1.282 + */ 1.283 + 1.284 + net.fortuna.ical4j.model.component.VEvent event = (VEvent) this.calendarComponent; 1.285 + 1.286 + //ComponentList ComList = this.calendar.getComponents(Component.VALARM); 1.287 + ComponentList ComList = event.getAlarms(); 1.288 + 1.289 + if (ComList != null) { 1.290 + for (Object objCom : ComList) { 1.291 + Component Com = (Component) objCom; 1.292 + Reminder = new ContentValues(); 1.293 + 1.294 + //Property ACTION = Com.getProperty("ACTION"); 1.295 + Property TRIGGER = Com.getProperty("TRIGGER"); 1.296 + if (TRIGGER != null) { 1.297 + Dur Duration = new Dur(TRIGGER.getValue()); 1.298 + //if (ACTION.getValue().equals("DISPLAY")) 1.299 + 1.300 + int intDuration = Duration.getMinutes() + Duration.getHours() * 60 + Duration.getDays() * 60 * 24; 1.301 + 1.302 + Reminder.put(Reminders.EVENT_ID, ContentUris.parseId(mAndroidEventUri)); 1.303 + Reminder.put(Reminders.METHOD, Reminders.METHOD_ALERT); 1.304 + Reminder.put(Reminders.MINUTES, intDuration); 1.305 + 1.306 + Result.add(Reminder); 1.307 + } 1.308 + } 1.309 + } 1.310 + return Result; 1.311 + } 1.312 + 1.313 + public java.util.ArrayList<ContentValues> getAttandees() { 1.314 + java.util.ArrayList<ContentValues> Result = new java.util.ArrayList<ContentValues>(); 1.315 + ContentValues Attendee; 1.316 + PropertyList Propertys = calendarComponent.getProperties(Property.ATTENDEE); 1.317 + if (Propertys != null) { 1.318 + for (Object objProperty : Propertys){ 1.319 + Property property = (Property) objProperty; 1.320 + Attendee = ReadAttendeeProperties(property,Property.ATTENDEE); 1.321 + if (Attendee != null) 1.322 + Result.add(Attendee); 1.323 + } 1.324 + } 1.325 + Propertys = calendarComponent.getProperties(Property.ORGANIZER); 1.326 + if (Propertys != null) { 1.327 + for (Object objProperty : Propertys){ 1.328 + Property property = (Property) objProperty; 1.329 + Attendee = ReadAttendeeProperties(property,Property.ORGANIZER); 1.330 + if (Attendee != null) 1.331 + Result.add(Attendee); 1.332 + } 1.333 + } 1.334 + 1.335 + 1.336 + return Result; 1.337 + } 1.338 + 1.339 + private String mstrcIcalPropertyError = "net.fortunal.ical4j.invalid:"; 1.340 + private ContentValues ReadAttendeeProperties(Property property, String Type) { 1.341 + ContentValues Attendee = null; 1.342 + 1.343 + ParameterList Parameters = property.getParameters(); 1.344 + Parameter CN = Parameters.getParameter(Cn.CN); 1.345 + Parameter ROLE = Parameters.getParameter(Role.ROLE); 1.346 + Parameter CUTYPE = Parameters.getParameter(CuType.CUTYPE); 1.347 + //Parameter RSVP = Parameters.getParameter("RSVP"); 1.348 + Parameter PARTSTAT = Parameters.getParameter(PartStat.PARTSTAT); 1.349 + 1.350 + String strCN = ""; 1.351 + String strROLE = ""; 1.352 + String strCUTYPE = ""; 1.353 + String strValue = property.getValue().replace("mailto:", ""); 1.354 + String strPARTSTAT = ""; 1.355 + 1.356 + if (strValue.startsWith(mstrcIcalPropertyError)) { 1.357 + strValue = strValue.replace(mstrcIcalPropertyError, ""); 1.358 + try { 1.359 + strValue = URLDecoder.decode(strValue, "UTF-8"); 1.360 + } catch (UnsupportedEncodingException e) { 1.361 + e.printStackTrace(); 1.362 + } 1.363 + } 1.364 + 1.365 + if (CN != null) 1.366 + strCN = CN.getValue(); 1.367 + if (ROLE != null) 1.368 + strROLE = ROLE.getValue(); 1.369 + if (CUTYPE != null) 1.370 + strCUTYPE = CUTYPE.getValue(); 1.371 + if (PARTSTAT != null) 1.372 + strPARTSTAT = PARTSTAT.getValue(); 1.373 + 1.374 + if (strCN.equals("")) { 1.375 + if (!strValue.equals("")) { 1.376 + strCN = strValue; 1.377 + } 1.378 + } 1.379 + 1.380 + if (!strCN.equals("")) { 1.381 + if (strCUTYPE.equals("") || strCUTYPE.equals("INDIVIDUAL")) { 1.382 + Attendee = new ContentValues(); 1.383 + 1.384 + Attendee.put(Attendees.EVENT_ID, ContentUris.parseId(mAndroidEventUri)); 1.385 + 1.386 + Attendee.put(Attendees.ATTENDEE_NAME, strCN); 1.387 + Attendee.put(Attendees.ATTENDEE_EMAIL, strValue); 1.388 + 1.389 + if (strROLE.equals("OPT-PARTICIPANT")) 1.390 + Attendee.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL); 1.391 + else if (strROLE.equals("NON-PARTICIPANT")) 1.392 + Attendee.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE); 1.393 + else if (strROLE.equals("REQ-PARTICIPANT")) 1.394 + Attendee.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED); 1.395 + else if (strROLE.equals("CHAIR")) 1.396 + Attendee.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED); 1.397 + else 1.398 + Attendee.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE); 1.399 + 1.400 + if (Type.equals(Property.ATTENDEE)) 1.401 + Attendee.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE); 1.402 + else if (Type.equals(Property.ORGANIZER)) 1.403 + Attendee.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER); 1.404 + else 1.405 + Attendee.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_NONE); 1.406 + 1.407 + if (strPARTSTAT.equals(PartStat.NEEDS_ACTION.getValue())) 1.408 + Attendee.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED); 1.409 + else if (strPARTSTAT.equals(PartStat.ACCEPTED.getValue())) 1.410 + Attendee.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_ACCEPTED); 1.411 + else if (strPARTSTAT.equals(PartStat.DECLINED.getValue())) 1.412 + Attendee.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_DECLINED); 1.413 + else if (strPARTSTAT.equals(PartStat.COMPLETED.getValue())) 1.414 + Attendee.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE); 1.415 + else if (strPARTSTAT.equals(PartStat.TENTATIVE.getValue())) 1.416 + Attendee.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_TENTATIVE); 1.417 + else 1.418 + Attendee.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED); 1.419 + 1.420 + } 1.421 + } 1.422 + 1.423 + return Attendee; 1.424 + } 1.425 + 1.426 + private long getAccessLevel() { 1.427 + long Result = Events.ACCESS_DEFAULT; 1.428 + String Value = ""; 1.429 + Property property = calendarComponent.getProperty(Property.CLASS); 1.430 + if (property != null) { 1.431 + Value = property.getValue(); 1.432 + if (Value.equals(Clazz.PUBLIC)) 1.433 + Result = Events.ACCESS_PUBLIC; 1.434 + else if (Value.equals(Clazz.PRIVATE)) 1.435 + Result = Events.ACCESS_PRIVATE; 1.436 + else if (Value.equals(Clazz.CONFIDENTIAL)) 1.437 + Result = Events.ACCESS_PRIVATE; // should be ACCESS_CONFIDENTIAL, but is not implemented within Android 1.438 + } 1.439 + 1.440 + return Result; 1.441 + } 1.442 + 1.443 + private int getStatus() { 1.444 + int Result = -1; 1.445 + String Value = ""; 1.446 + Property property = calendarComponent.getProperty(Property.STATUS); 1.447 + if (property != null) { 1.448 + Value = property.getValue(); 1.449 + if (Value.equals(Status.VEVENT_CONFIRMED.getValue())) 1.450 + Result = Events.STATUS_CONFIRMED; 1.451 + else if (Value.equals(Status.VEVENT_CANCELLED.getValue())) 1.452 + Result = Events.STATUS_CANCELED; 1.453 + else if (Value.equals(Status.VEVENT_TENTATIVE.getValue())) 1.454 + Result = Events.STATUS_TENTATIVE; 1.455 + } 1.456 + 1.457 + return Result; 1.458 + } 1.459 + 1.460 + private String getDescription() { 1.461 + String Result = null; 1.462 + Property property = calendarComponent.getProperty(Property.DESCRIPTION); 1.463 + if (property != null) 1.464 + Result = property.getValue(); 1.465 + 1.466 + return Result; 1.467 + } 1.468 + 1.469 + private String getLocation() { 1.470 + String Result = null; 1.471 + Property property = calendarComponent.getProperty(Property.LOCATION); 1.472 + if (property != null) 1.473 + Result = property.getValue(); 1.474 + 1.475 + return Result; 1.476 + } 1.477 + 1.478 + private String getTitle() { 1.479 + Property property = calendarComponent.getProperty(Property.SUMMARY); 1.480 + if (property != null) 1.481 + return property.getValue(); 1.482 + else 1.483 + return "**unkonwn**"; 1.484 + } 1.485 + 1.486 + private String getRRule() { 1.487 + String Result = null; 1.488 + Property property = calendarComponent.getProperty(Property.RRULE); 1.489 + if (property != null) 1.490 + Result = property.getValue(); 1.491 + 1.492 + return Result; 1.493 + } 1.494 + 1.495 + private String getExRule() { 1.496 + String Result = null; 1.497 + Property property = calendarComponent.getProperty(Property.EXRULE); 1.498 + if (property != null) 1.499 + Result = property.getValue(); 1.500 + 1.501 + return Result; 1.502 + } 1.503 + 1.504 + private String getRDate() { 1.505 + String Result = null; 1.506 + 1.507 + java.util.ArrayList<String> ExDates = this.getRDates(); 1.508 + for (String Value: ExDates) { 1.509 + if (Result == null) 1.510 + Result = ""; 1.511 + if (!Result.isEmpty()) 1.512 + Result += ","; 1.513 + Result += Value; 1.514 + } 1.515 + 1.516 + return Result; 1.517 + } 1.518 + 1.519 + private java.util.ArrayList<String> getRDates() { 1.520 + java.util.ArrayList<String> Result = new java.util.ArrayList<String>(); 1.521 + PropertyList Propertys = calendarComponent.getProperties(Property.RDATE); 1.522 + if (Propertys != null) { 1.523 + Property property; 1.524 + for (Object objProperty : Propertys){ 1.525 + property = (Property) objProperty; 1.526 + Result.add(property.getValue()); 1.527 + } 1.528 + } 1.529 + 1.530 + return Result; 1.531 + } 1.532 + 1.533 + private String getExDate() { 1.534 + String Result = null; 1.535 + 1.536 + java.util.ArrayList<String> ExDates = this.getExDates(); 1.537 + for (String Value: ExDates) { 1.538 + if (Result == null) 1.539 + Result = ""; 1.540 + if (!Result.isEmpty()) 1.541 + Result += ","; 1.542 + Result += Value; 1.543 + } 1.544 + 1.545 + return Result; 1.546 + } 1.547 + 1.548 + private java.util.ArrayList<String> getExDates() { 1.549 + java.util.ArrayList<String> Result = new java.util.ArrayList<String>(); 1.550 + PropertyList Propertys = calendarComponent.getProperties(Property.EXDATE); 1.551 + if (Propertys != null) { 1.552 + Property property; 1.553 + for (Object objProperty : Propertys){ 1.554 + property = (Property) objProperty; 1.555 + Result.add(property.getValue()); 1.556 + } 1.557 + } 1.558 + 1.559 + return Result; 1.560 + } 1.561 + 1.562 + private String getUid() { 1.563 + String Result = ""; 1.564 + Property prop = calendarComponent.getProperty(Property.UID); 1.565 + if (prop != null) { 1.566 + Result = prop.getValue(); 1.567 + } 1.568 + 1.569 + return Result; 1.570 + } 1.571 + 1.572 + private Long getTimestamp(Property prop) { 1.573 + Long Result = null; 1.574 + String strTimeZone = ""; 1.575 + //TimeZone timeZone = null; 1.576 + 1.577 + try { 1.578 + String strDate = prop.getValue(); 1.579 + 1.580 + Parameter parAllDay = prop.getParameter("VALUE"); 1.581 + if (parAllDay != null) { 1.582 + if (parAllDay.getValue().equals("DATE")) { 1.583 + mAllDay = true; 1.584 + strDate += "T000000Z"; 1.585 + } 1.586 + } 1.587 + 1.588 + Parameter propTZ = prop.getParameter(Property.TZID); 1.589 + if (propTZ != null) 1.590 + strTimeZone = propTZ.getValue(); 1.591 + 1.592 + //TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry(); 1.593 + //if (!strTimeZone.equals("")) 1.594 + // timeZone = registry.getTimeZone(strTimeZone); 1.595 + 1.596 + //if (timeZone != null) { 1.597 + if (!strTimeZone.equals("")) { 1.598 + //Result = new DateTime(strDate, timeZone); 1.599 + //Result1 = Result.getTime(); 1.600 + 1.601 + //20130331T120000 1.602 + int Year = Integer.parseInt(strDate.substring(0, 4)); 1.603 + int Month = Integer.parseInt(strDate.substring(4, 6)) - 1; 1.604 + int Day = Integer.parseInt(strDate.substring(6, 8)); 1.605 + int Hour = Integer.parseInt(strDate.substring(9, 11)); 1.606 + int Minute = Integer.parseInt(strDate.substring(11, 13)); 1.607 + int Second = Integer.parseInt(strDate.substring(13, 15)); 1.608 + 1.609 + // time in UTC 1.610 + java.util.TimeZone jtz = java.util.TimeZone.getTimeZone("UTC"); 1.611 + java.util.Calendar cal = java.util.GregorianCalendar.getInstance(jtz); 1.612 + cal.set(Year, Month, Day, Hour, Minute, Second); 1.613 + cal.set(java.util.Calendar.MILLISECOND, 0); 1.614 + Result = cal.getTimeInMillis(); 1.615 + 1.616 + // get the timezone 1.617 + String[] IDs = java.util.TimeZone.getAvailableIDs(); 1.618 + Boolean Found = false; 1.619 + for (int i = 0; i < IDs.length; i++) { 1.620 + Found = Found || IDs[i].equals(strTimeZone); 1.621 + } 1.622 + if (Found) { 1.623 + jtz = java.util.TimeZone.getTimeZone(strTimeZone); 1.624 + 1.625 + // subtract the offset 1.626 + Result -= jtz.getRawOffset(); 1.627 + 1.628 + // remove dst 1.629 + if (jtz.inDaylightTime(new java.util.Date(Result))) 1.630 + Result -= jtz.getDSTSavings(); 1.631 + 1.632 + } else { 1.633 + if (mTimeZone != null) { 1.634 + // subtract the offset 1.635 + Result -= mTimeZone.getRawOffset(); 1.636 + 1.637 + // remove dst 1.638 + if (mTimeZone.inDaylightTime(new java.util.Date(Result))) 1.639 + Result -= mTimeZone.getDSTSavings(); 1.640 + } else { 1.641 + // unknown Time? 1.642 + // treat as local time, should not happen too often :) 1.643 + Result = new DateTime(strDate).getTime(); 1.644 + } 1.645 + } 1.646 + } else { 1.647 + if (strDate.endsWith("Z")) { 1.648 + // GMT or UTC 1.649 + Result = new DateTime(strDate).getTime(); 1.650 + } else { 1.651 + // unknown Time? 1.652 + // treat as local time, should not happen too often :) 1.653 + Result = new DateTime(strDate).getTime(); 1.654 + } 1.655 + } 1.656 + 1.657 + } catch (ParseException e) { 1.658 + e.printStackTrace(); 1.659 + } 1.660 + 1.661 + return Result; 1.662 + } 1.663 + 1.664 + private long getStartTime() { 1.665 + long Result = 0; 1.666 + Property prop; 1.667 + /* 1.668 + * DTSTART;TZID=Europe/Berlin:20120425T080000 1.669 + * DTSTART;TZID=(GMT+01.00) Sarajevo/Warsaw/Zagreb:20120305T104500 1.670 + * DTSTART:20120308T093000Z 1.671 + * DTSTART;VALUE=DATE:20120709 1.672 + * DTSTART;TZID=Europe/Berlin:20130330T100000 1.673 + */ 1.674 + 1.675 + prop = calendarComponent.getProperty(Property.DTSTART); 1.676 + if (prop != null) { 1.677 + Parameter propTZ = prop.getParameter(Property.TZID); 1.678 + if (propTZ != null) 1.679 + mstrTimeZoneStart = propTZ.getValue(); 1.680 + Result = getTimestamp(prop); 1.681 + } 1.682 + 1.683 + return Result; 1.684 + } 1.685 + 1.686 + private long getEndTime() { 1.687 + long Result = 0; 1.688 + Property propDtEnd; 1.689 + Property propDuration; 1.690 + 1.691 + propDtEnd = calendarComponent.getProperty(Property.DTEND); 1.692 + propDuration = calendarComponent.getProperty(Property.DURATION); 1.693 + if (propDtEnd != null) { 1.694 + Parameter propTZ = propDtEnd.getParameter(Property.TZID); 1.695 + if (propTZ != null) 1.696 + mstrTimeZoneEnd = propTZ.getValue(); 1.697 + Result = getTimestamp(propDtEnd); 1.698 + 1.699 + } else if (propDuration != null) { 1.700 + Result = 0; 1.701 + long Start = this.getStartTime(); 1.702 + String strDuration = propDuration.getValue(); 1.703 + Dur dur = new Dur(strDuration); 1.704 + Result = Start 1.705 + + dur.getSeconds() * 1000 1.706 + + dur.getMinutes() * 60 * 1000 1.707 + + dur.getHours() * 60 * 60 * 1000 1.708 + + dur.getDays() * 60 * 60 * 24 * 1000; 1.709 + 1.710 + mstrTimeZoneEnd = mstrTimeZoneStart; 1.711 + } 1.712 + 1.713 + 1.714 + return Result; 1.715 + } 1.716 + 1.717 + private String getTimeZoneStart() { 1.718 + String Result = "GMT"; 1.719 + 1.720 + if (!mstrTimeZoneStart.equals("")) { 1.721 + Result = mstrTimeZoneStart; 1.722 + } 1.723 + 1.724 + return Result; 1.725 + } 1.726 + 1.727 + private String getTimeZoneEnd() { 1.728 + String Result = "GMT"; 1.729 + 1.730 + if (!mstrTimeZoneEnd.equals("")) { 1.731 + Result = mstrTimeZoneEnd; 1.732 + } 1.733 + 1.734 + return Result; 1.735 + } 1.736 + 1.737 + 1.738 + private String getDuration() { 1.739 + String Result = ""; 1.740 + Property prop = calendarComponent.getProperty("DURATION"); 1.741 + 1.742 + if (prop != null) { 1.743 + //DURATION:PT1H 1.744 + Result = prop.getValue(); 1.745 + } else { 1.746 + // no DURATION given by this event. we have to calculate it by ourself 1.747 + Result = "P"; 1.748 + long Start = this.getStartTime(); 1.749 + long End = this.getEndTime(); 1.750 + long Duration = 0; 1.751 + if (End != 0) 1.752 + Duration = (End - Start) / 1000; // get rid of the milliseconds, they cann't be described with RFC2445-Duration 1.753 + 1.754 + if (Duration < 0) { 1.755 + Duration = 0; 1.756 + } 1.757 + int Days = (int) Math.ceil(Duration / 24 / 60 / 60); 1.758 + int Hours = (int) Math.ceil((Duration - (Days * 24 * 60 * 60)) / 60 / 60); 1.759 + int Minutes = (int) Math.ceil((Duration - (Days * 24 * 60 * 60) - (Hours * 60 * 60)) / 60); 1.760 + int Seconds = (int) (Duration - (Days * 24 * 60 * 60) - (Hours * 60 * 60) - (Minutes * 60)); 1.761 + 1.762 + if (Days > 0) 1.763 + Result += String.valueOf(Days) + "D"; 1.764 + 1.765 + if (!mAllDay) { 1.766 + //if a ALL_DAY event occurs, there is no need for hours, minutes and seconds (Android doesn't understand them) 1.767 + Result += "T"; 1.768 + Result += String.valueOf(Hours) + "H"; 1.769 + Result += String.valueOf(Minutes) + "M"; 1.770 + Result += String.valueOf(Seconds) + "S"; 1.771 + } 1.772 + } 1.773 + 1.774 + return Result; 1.775 + } 1.776 + 1.777 + private int getAllDay() { 1.778 + int Result = 0; 1.779 + 1.780 + if (mAllDay) 1.781 + Result = 1; 1.782 + 1.783 + return Result; 1.784 + } 1.785 + 1.786 + /** 1.787 + * opens the first items of the event 1.788 + * @return success of this function 1.789 + * @see AndroidEvent#createIcs() 1.790 + * @see CalendarEvent#fetchBody() 1.791 + * @throws CaldavProtocolException 1.792 + * @throws IOException 1.793 + * @throws ParserException 1.794 + */ 1.795 + private boolean parseIcs() throws CaldavProtocolException, IOException, ParserException { 1.796 + boolean Error = false; 1.797 + 1.798 + CalendarBuilder builder = new CalendarBuilder(); 1.799 + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true); 1.800 + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true); 1.801 + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION, true); 1.802 + CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_OUTLOOK_COMPATIBILITY, true); 1.803 + 1.804 + StringReader reader = new StringReader(this.stringIcs); 1.805 + try { 1.806 + this.calendar = builder.build(reader); 1.807 + } catch (ParserException ex) { 1.808 + // ical4j fails with this: "Cannot set timezone for UTC properties" 1.809 + // CREATED;TZID=America/New_York:20130129T140250 1.810 + Error = true; 1.811 + } 1.812 + 1.813 + if (!Error) { 1.814 + ComponentList components = null; 1.815 + components = this.calendar.getComponents(Component.VEVENT); 1.816 + if (components.size() == 0) { 1.817 + components = this.calendar.getComponents(Component.VTODO); 1.818 + if (components.size() == 0) { 1.819 + throw new CaldavProtocolException("unknown events in ICS"); 1.820 + } else { 1.821 + Log.e(TAG, "unsupported event TODO in ICS"); 1.822 + Error = true; 1.823 + } 1.824 + } else if (components.size() > 1) { 1.825 + Log.e(TAG, "Several events in ICS -> only first will be processed"); 1.826 + } 1.827 + 1.828 + // get the TimeZone information 1.829 + Component mCom = this.calendar.getComponent(Component.VTIMEZONE); 1.830 + if (mCom != null) 1.831 + mVTimeZone = (VTimeZone) this.calendar.getComponent(Component.VTIMEZONE); 1.832 + if (mVTimeZone != null) 1.833 + mTimeZone = new TimeZone(mVTimeZone); 1.834 + 1.835 + if (!Error) 1.836 + calendarComponent = (Component) components.get(0); 1.837 + } 1.838 + 1.839 + return !Error; 1.840 + } 1.841 + 1.842 + /** 1.843 + * searches for an android event 1.844 + * @param androidCalendar 1.845 + * @return the android event 1.846 + * @throws RemoteException 1.847 + */ 1.848 + public AndroidEvent getAndroidEvent(DavCalendar androidCalendar) throws RemoteException { 1.849 + boolean Error = false; 1.850 + Uri uriEvents = Events.CONTENT_URI; 1.851 + Uri uriAttendee = Attendees.CONTENT_URI; 1.852 + Uri uriReminder = Reminders.CONTENT_URI; 1.853 + AndroidEvent androidEvent = null; 1.854 + 1.855 + String selection = "(" + Events._SYNC_ID + " = ?)"; 1.856 + String[] selectionArgs = new String[] {this.getUri().toString()}; 1.857 + Cursor curEvent = this.mProvider.query(uriEvents, null, selection, selectionArgs, null); 1.858 + 1.859 + Cursor curAttendee = null; 1.860 + Cursor curReminder = null; 1.861 + 1.862 + if (curEvent == null) { 1.863 + Error = true; 1.864 + } 1.865 + if (!Error) { 1.866 + if (curEvent.getCount() == 0) { 1.867 + Error = true; 1.868 + } 1.869 + } 1.870 + if (!Error) { 1.871 + curEvent.moveToNext(); 1.872 + 1.873 + long EventID = curEvent.getLong(curEvent.getColumnIndex(Events._ID)); 1.874 + Uri returnedUri = ContentUris.withAppendedId(uriEvents, EventID); 1.875 + 1.876 + //androidEvent = new AndroidEvent(this.mAccount, this.mProvider, returnedUri, androidCalendar.getAndroidCalendarUri()); 1.877 + androidEvent = new AndroidEvent(returnedUri, androidCalendar.getAndroidCalendarUri()); 1.878 + androidEvent.readContentValues(curEvent); 1.879 + 1.880 + selection = "(" + Attendees.EVENT_ID + " = ?)"; 1.881 + selectionArgs = new String[] {String.valueOf(EventID)}; 1.882 + curAttendee = this.mProvider.query(uriAttendee, null, selection, selectionArgs, null); 1.883 + selection = "(" + Reminders.EVENT_ID + " = ?)"; 1.884 + selectionArgs = new String[] {String.valueOf(EventID)}; 1.885 + curReminder = this.mProvider.query(uriReminder, null, selection, selectionArgs, null); 1.886 + androidEvent.readAttendees(curAttendee); 1.887 + androidEvent.readReminder(curReminder); 1.888 + curAttendee.close(); 1.889 + curReminder.close(); 1.890 + } 1.891 + curEvent.close(); 1.892 + 1.893 + return androidEvent; 1.894 + } 1.895 + 1.896 + /** 1.897 + * creates a new androidEvent from a given calendarEvent 1.898 + * @param androidCalendar 1.899 + * @return 1.900 + * @throws ClientProtocolException 1.901 + * @throws IOException 1.902 + * @throws CaldavProtocolException 1.903 + * @throws RemoteException 1.904 + * @throws ParserException 1.905 + * @see {@link SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats)} 1.906 + */ 1.907 + public boolean createAndroidEvent(DavCalendar androidCalendar) throws ClientProtocolException, IOException, CaldavProtocolException, RemoteException, ParserException { 1.908 + boolean Result = false; 1.909 + boolean BodyFetched = this.fetchBody(); 1.910 + int CountAttendees = 0; 1.911 + int CountReminders = 0; 1.912 + 1.913 + if (BodyFetched) { 1.914 + //calendarEvent.readContentValues(calendarUri); 1.915 + this.readContentValues(); 1.916 + this.setAndroidCalendarId(ContentUris.parseId(androidCalendar.getAndroidCalendarUri())); 1.917 + 1.918 + Uri uri = this.mProvider.insert(asSyncAdapter(Events.CONTENT_URI, this.mAccount.name, this.mAccount.type), this.ContentValues); 1.919 + this.setAndroidEventUri(uri); 1.920 + 1.921 + Log.d(TAG, "Creating calendar event for " + uri.toString()); 1.922 + 1.923 + //check the attendees 1.924 + java.util.ArrayList<ContentValues> AttendeeList = this.getAttandees(); 1.925 + for (ContentValues Attendee : AttendeeList) { 1.926 + this.mProvider.insert(Attendees.CONTENT_URI, Attendee); 1.927 + CountAttendees += 1; 1.928 + } 1.929 + 1.930 + //check the reminders 1.931 + java.util.ArrayList<ContentValues> ReminderList = this.getReminders(); 1.932 + for (ContentValues Reminder : ReminderList) { 1.933 + this.mProvider.insert(Reminders.CONTENT_URI, Reminder); 1.934 + CountReminders += 1; 1.935 + } 1.936 + 1.937 + if ((CountAttendees > 0) || (CountReminders > 0)) { 1.938 + //the events gets dirty when attendees or reminders were added 1.939 + AndroidEvent androidEvent = this.getAndroidEvent(androidCalendar); 1.940 + 1.941 + androidEvent.ContentValues.put(Events.DIRTY, 0); 1.942 + int RowCount = this.mProvider.update(asSyncAdapter(androidEvent.getUri(), this.mAccount.name, this.mAccount.type), androidEvent.ContentValues, null, null); 1.943 + Result = (RowCount == 1); 1.944 + } else { 1.945 + Result = true; 1.946 + } 1.947 + 1.948 + 1.949 + } 1.950 + return Result; 1.951 + } 1.952 + 1.953 + /** 1.954 + * the android event is getting updated 1.955 + * @param provider 1.956 + * @param account 1.957 + * @param androidEvent 1.958 + * @param calendarEvent 1.959 + * @return 1.960 + * @throws ClientProtocolException 1.961 + * @throws IOException 1.962 + * @throws CaldavProtocolException 1.963 + * @throws RemoteException 1.964 + * @throws ParserException 1.965 + * @see {@link SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, Calendar, SyncStats)} 1.966 + */ 1.967 + public boolean updateAndroidEvent(AndroidEvent androidEvent) throws ClientProtocolException, IOException, CaldavProtocolException, RemoteException, ParserException { 1.968 + boolean BodyFetched = this.fetchBody(); 1.969 + int Rows = 0; 1.970 + 1.971 + if (BodyFetched) { 1.972 + this.readContentValues(); 1.973 + this.setAndroidCalendarId(androidEvent.getAndroidCalendarId()); 1.974 + this.setAndroidEventUri(androidEvent.getUri()); 1.975 + 1.976 + Log.d(TAG, "AndroidEvent is dirty: " + androidEvent.ContentValues.getAsString(Events.DIRTY)); 1.977 + 1.978 + if (androidEvent.checkEventValuesChanged(this.ContentValues)) { 1.979 + // just set the raw data from server event into android event 1.980 + if (androidEvent.ContentValues.containsKey(Event.RAWDATA)) 1.981 + androidEvent.ContentValues.remove(Event.RAWDATA); 1.982 + androidEvent.ContentValues.put(Event.RAWDATA, this.ContentValues.getAsString(Event.RAWDATA)); 1.983 + 1.984 + //update the attendees and reminders 1.985 + this.updateAndroidAttendees(); 1.986 + this.updateAndroidReminder(); 1.987 + 1.988 + androidEvent.ContentValues.put(Events.DIRTY, 0); // the event is now in sync 1.989 + Log.d(TAG, "Update calendar event: for "+androidEvent.getUri()); 1.990 + 1.991 + Rows = mProvider.update(asSyncAdapter(androidEvent.getUri(), mAccount.name, mAccount.type), androidEvent.ContentValues, null, null); 1.992 + //Log.i(TAG, "Updated calendar event: rows effected " + Rows.toString()); 1.993 + } else { 1.994 + Log.d(TAG, "Update calendar event not needed: for "+androidEvent.getUri()); 1.995 + } 1.996 + } 1.997 + return (Rows == 1); 1.998 + } 1.999 + 1.1000 + /** 1.1001 + * updates the attendees from a calendarEvent to its androidEvent. 1.1002 + * the calendarEvent has to know its androidEvent via {@link CalendarEvent#setAndroidEventUri(Uri)} 1.1003 + * @param provider 1.1004 + * @return 1.1005 + * @see SyncAdapter#updateAndroidEvent(ContentProviderClient, Account, AndroidEvent, CalendarEvent) 1.1006 + */ 1.1007 + private boolean updateAndroidAttendees() { 1.1008 + boolean Result = false; 1.1009 + 1.1010 + try { 1.1011 + String mSelectionClause = "(" + Attendees.EVENT_ID + " = ?)"; 1.1012 + String[] mSelectionArgs = {Long.toString(ContentUris.parseId(this.getAndroidEventUri())) }; 1.1013 + int RowDelete; 1.1014 + RowDelete = this.mProvider.delete(Attendees.CONTENT_URI, mSelectionClause, mSelectionArgs); 1.1015 + Log.d(TAG, "Attendees Deleted:" + String.valueOf(RowDelete)); 1.1016 + 1.1017 + java.util.ArrayList<ContentValues> AttendeeList = this.getAttandees(); 1.1018 + for (ContentValues Attendee : AttendeeList) { 1.1019 + this.mProvider.insert(Attendees.CONTENT_URI, Attendee); 1.1020 + } 1.1021 + Log.d(TAG, "Attendees Inserted:" + String.valueOf(AttendeeList.size())); 1.1022 + Result = true; 1.1023 + } catch (RemoteException e) { 1.1024 + e.printStackTrace(); 1.1025 + } 1.1026 + 1.1027 + return Result; 1.1028 + } 1.1029 + 1.1030 + /** 1.1031 + * update the reminders from a calendarEvent to its androidEvent. 1.1032 + * the calendarEvent has to know its androidEvent via {@link CalendarEvent#setAndroidEventUri(Uri)} 1.1033 + * @param provider 1.1034 + * @return 1.1035 + * @see SyncAdapter#updateAndroidEvent(ContentProviderClient, Account, AndroidEvent, CalendarEvent) 1.1036 + */ 1.1037 + private boolean updateAndroidReminder() { 1.1038 + boolean Result = false; 1.1039 + 1.1040 + try { 1.1041 + String mSelectionClause = "(" + Reminders.EVENT_ID + " = ?)"; 1.1042 + String[] mSelectionArgs = {Long.toString(ContentUris.parseId(this.getAndroidEventUri())) }; 1.1043 + int RowDelete; 1.1044 + RowDelete = this.mProvider.delete(Reminders.CONTENT_URI, mSelectionClause, mSelectionArgs); 1.1045 + Log.d(TAG, "Reminders Deleted:" + String.valueOf(RowDelete)); 1.1046 + 1.1047 + 1.1048 + Uri ReminderUri; 1.1049 + java.util.ArrayList<ContentValues> ReminderList = this.getReminders(); 1.1050 + for (ContentValues Reminder : ReminderList) { 1.1051 + ReminderUri = this.mProvider.insert(Reminders.CONTENT_URI, Reminder); 1.1052 + System.out.println(ReminderUri); 1.1053 + } 1.1054 + Log.d(TAG, "Reminders Inserted:" + String.valueOf(ReminderList.size())); 1.1055 + 1.1056 + Result = true; 1.1057 + } catch (RemoteException e) { 1.1058 + e.printStackTrace(); 1.1059 + } 1.1060 + 1.1061 + return Result; 1.1062 + } 1.1063 + 1.1064 + private static Uri asSyncAdapter(Uri uri, String account, String accountType) { 1.1065 + return uri.buildUpon() 1.1066 + .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true") 1.1067 + .appendQueryParameter(Calendars.ACCOUNT_NAME, account) 1.1068 + .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); 1.1069 + } 1.1070 +} 1.1071 +