mirror of
https://github.com/etesync/android
synced 2025-02-17 01:52:03 +00:00
Version 0.4.4
* allow to enter account name at the end of account setup (fixes #13) * advise user to enter email address as account name (closes #24) * support for iCal TRANSP (availability free/busy field) * create better UIDs using iCal4j UidGenerator and Settings.Secure.ANDROID_ID * better ORGANIZER/ATTENDEE support, but there are big Android issues yet * various improvements and bug fixes
This commit is contained in:
parent
44cf628dd6
commit
1986837be8
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="at.bitfire.davdroid"
|
package="at.bitfire.davdroid"
|
||||||
android:versionCode="16"
|
android:versionCode="17"
|
||||||
android:versionName="0.4.3-alpha" >
|
android:versionName="0.4.4-alpha" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="14"
|
android:minSdkVersion="14"
|
||||||
|
BIN
res/drawable-hdpi/extra_actions_about.png
Normal file
BIN
res/drawable-hdpi/extra_actions_about.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 683 B |
BIN
res/drawable-mdpi/extra_actions_about.png
Normal file
BIN
res/drawable-mdpi/extra_actions_about.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 465 B |
BIN
res/drawable-xhdpi/extra_actions_about.png
Normal file
BIN
res/drawable-xhdpi/extra_actions_about.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 860 B |
BIN
res/drawable-xxhdpi/extra_actions_about.png
Normal file
BIN
res/drawable-xxhdpi/extra_actions_about.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
50
res/layout/account_details.xml
Normal file
50
res/layout/account_details.xml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:scrollbars="vertical" >
|
||||||
|
|
||||||
|
<GridLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:columnCount="2"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:useDefaultMargins="true" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_columnSpan="2"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:text="@string/account_details"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:text="@string/account_name"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/account_name"
|
||||||
|
android:layout_gravity="fill_horizontal"
|
||||||
|
android:hint="@string/account_name_hint"
|
||||||
|
android:inputType="textEmailAddress" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/account_name_info"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_columnSpan="2"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:drawableLeft="@drawable/extra_actions_about"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:text="@string/account_name_info"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_gravity="left|top"
|
||||||
|
android:layout_row="3" />
|
||||||
|
|
||||||
|
</GridLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
11
res/menu/account_details.xml
Normal file
11
res/menu/account_details.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/add_account"
|
||||||
|
android:icon="@drawable/navigation_accept"
|
||||||
|
android:showAsAction="always|withText"
|
||||||
|
android:title="@string/add_account">
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</menu>
|
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" ><item
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
android:id="@+id/add_account"
|
|
||||||
android:icon="@drawable/navigation_accept"
|
<item
|
||||||
|
android:id="@+id/next"
|
||||||
|
android:icon="@drawable/navigation_forward"
|
||||||
android:showAsAction="always|withText"
|
android:showAsAction="always|withText"
|
||||||
android:title="@string/add_account" android:orderInCategory="2">
|
android:title="@string/next">
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
@ -75,5 +75,11 @@
|
|||||||
* <a href="http://simple.sourceforge.net/">Simple XML Serialization</a> (<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>)<br/>
|
* <a href="http://simple.sourceforge.net/">Simple XML Serialization</a> (<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>)<br/>
|
||||||
* <a href="http://projectlombok.org/">Project Lombok</a> (<a href="http://opensource.org/licenses/mit-license.php">MIT License</a>)</p>
|
* <a href="http://projectlombok.org/">Project Lombok</a> (<a href="http://opensource.org/licenses/mit-license.php">MIT License</a>)</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
|
<string name="account_details">Konto-Details</string>
|
||||||
|
<string name="account_name">Kontoname:</string>
|
||||||
|
<string name="account_name_hint">Mein CalDAV/CardDAV-Konto</string>
|
||||||
|
<string name="email_address">Email-Adresse:</string>
|
||||||
|
<string name="organizer_hint">"ORGANIZER der von Ihnen angelegten Termine; notwendig für Teilnehmer-Info"</string>
|
||||||
|
<string name="account_name_info">"Verwenden Sie Ihre Email-Addresse als Kontoname, da Android den Kontonamen als ORGANIZER-Feld in Terminen benutzt. Sie können keine zwei Konten mit dem gleichen Namen anlegen.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -83,5 +83,11 @@
|
|||||||
* <a href="http://simple.sourceforge.net/">Simple XML Serialization</a> (<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>)<br/>
|
* <a href="http://simple.sourceforge.net/">Simple XML Serialization</a> (<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>)<br/>
|
||||||
* <a href="http://projectlombok.org/">Project Lombok</a> (<a href="http://opensource.org/licenses/mit-license.php">MIT License</a>)</p>
|
* <a href="http://projectlombok.org/">Project Lombok</a> (<a href="http://opensource.org/licenses/mit-license.php">MIT License</a>)</p>
|
||||||
]]></string>
|
]]></string>
|
||||||
|
<string name="account_details">Account details</string>
|
||||||
|
<string name="account_name">Account name:</string>
|
||||||
|
<string name="account_name_hint">My CalDAV/CardDAV Account</string>
|
||||||
|
<string name="email_address">Email address:</string>
|
||||||
|
<string name="organizer_hint">"ORGANIZER of your events; required if you use attendee info"</string>
|
||||||
|
<string name="account_name_info">"Use your email address as account name because Android will use the account name as ORGANIZER field for events you create. You can't have two accounts with the same name.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -9,7 +9,7 @@ package at.bitfire.davdroid;
|
|||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
public static final String
|
public static final String
|
||||||
APP_VERSION = "0.4.3-alpha",
|
APP_VERSION = "0.4.4-alpha",
|
||||||
|
|
||||||
ACCOUNT_TYPE = "bitfire.at.davdroid",
|
ACCOUNT_TYPE = "bitfire.at.davdroid",
|
||||||
|
|
||||||
|
@ -50,12 +50,13 @@ import net.fortuna.ical4j.model.property.RDate;
|
|||||||
import net.fortuna.ical4j.model.property.RRule;
|
import net.fortuna.ical4j.model.property.RRule;
|
||||||
import net.fortuna.ical4j.model.property.Status;
|
import net.fortuna.ical4j.model.property.Status;
|
||||||
import net.fortuna.ical4j.model.property.Summary;
|
import net.fortuna.ical4j.model.property.Summary;
|
||||||
|
import net.fortuna.ical4j.model.property.Transp;
|
||||||
import net.fortuna.ical4j.model.property.Uid;
|
import net.fortuna.ical4j.model.property.Uid;
|
||||||
import net.fortuna.ical4j.model.property.Version;
|
import net.fortuna.ical4j.model.property.Version;
|
||||||
import net.fortuna.ical4j.util.UidGenerator;
|
|
||||||
import android.text.format.Time;
|
import android.text.format.Time;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
|
import at.bitfire.davdroid.syncadapter.DavSyncAdapter;
|
||||||
|
|
||||||
|
|
||||||
public class Event extends Resource {
|
public class Event extends Resource {
|
||||||
@ -76,6 +77,7 @@ public class Event extends Resource {
|
|||||||
@Getter @Setter private Boolean forPublic;
|
@Getter @Setter private Boolean forPublic;
|
||||||
@Getter @Setter private Status status;
|
@Getter @Setter private Status status;
|
||||||
|
|
||||||
|
@Getter @Setter private boolean opaque;
|
||||||
|
|
||||||
@Getter @Setter private Organizer organizer;
|
@Getter @Setter private Organizer organizer;
|
||||||
@Getter private List<Attendee> attendees = new LinkedList<Attendee>();
|
@Getter private List<Attendee> attendees = new LinkedList<Attendee>();
|
||||||
@ -122,8 +124,7 @@ public class Event extends Resource {
|
|||||||
uid = event.getUid().getValue();
|
uid = event.getUid().getValue();
|
||||||
else {
|
else {
|
||||||
Log.w(TAG, "Received VEVENT without UID, generating new one");
|
Log.w(TAG, "Received VEVENT without UID, generating new one");
|
||||||
UidGenerator uidGenerator = new UidGenerator(Integer.toString(android.os.Process.myPid()));
|
uid = DavSyncAdapter.generateUID();
|
||||||
uid = uidGenerator.generateUid().getValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dtStart = event.getStartDate(); validateTimeZone(dtStart);
|
dtStart = event.getStartDate(); validateTimeZone(dtStart);
|
||||||
@ -144,6 +145,10 @@ public class Event extends Resource {
|
|||||||
|
|
||||||
status = event.getStatus();
|
status = event.getStatus();
|
||||||
|
|
||||||
|
opaque = true;
|
||||||
|
if (event.getTransparency() == Transp.TRANSPARENT)
|
||||||
|
opaque = false;
|
||||||
|
|
||||||
organizer = event.getOrganizer();
|
organizer = event.getOrganizer();
|
||||||
for (Object o : event.getProperties(Property.ATTENDEE))
|
for (Object o : event.getProperties(Property.ATTENDEE))
|
||||||
attendees.add((Attendee)o);
|
attendees.add((Attendee)o);
|
||||||
@ -196,6 +201,8 @@ public class Event extends Resource {
|
|||||||
|
|
||||||
if (status != null)
|
if (status != null)
|
||||||
props.add(status);
|
props.add(status);
|
||||||
|
if (!opaque)
|
||||||
|
props.add(Transp.TRANSPARENT);
|
||||||
|
|
||||||
if (organizer != null)
|
if (organizer != null)
|
||||||
props.add(organizer);
|
props.add(organizer);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package at.bitfire.davdroid.resource;
|
package at.bitfire.davdroid.resource;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -120,7 +121,10 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
values.put(Calendars.CALENDAR_COLOR, color);
|
values.put(Calendars.CALENDAR_COLOR, color);
|
||||||
values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
|
values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER);
|
||||||
values.put(Calendars.ALLOWED_AVAILABILITY, Events.AVAILABILITY_BUSY + "," + Events.AVAILABILITY_FREE + "," + Events.AVAILABILITY_TENTATIVE);
|
values.put(Calendars.ALLOWED_AVAILABILITY, Events.AVAILABILITY_BUSY + "," + Events.AVAILABILITY_FREE + "," + Events.AVAILABILITY_TENTATIVE);
|
||||||
values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Attendees.TYPE_NONE + "," + Attendees.TYPE_REQUIRED + "," + Attendees.TYPE_OPTIONAL + "," + Attendees.TYPE_RESOURCE);
|
values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Attendees.TYPE_NONE + "," + Attendees.TYPE_OPTIONAL + "," + Attendees.TYPE_REQUIRED + "," + Attendees.TYPE_RESOURCE);
|
||||||
|
values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);
|
||||||
|
values.put(Calendars.CAN_ORGANIZER_RESPOND, 1);
|
||||||
|
values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1);
|
||||||
values.put(Calendars.OWNER_ACCOUNT, account.name);
|
values.put(Calendars.OWNER_ACCOUNT, account.name);
|
||||||
values.put(Calendars.SYNC_EVENTS, 1);
|
values.put(Calendars.SYNC_EVENTS, 1);
|
||||||
values.put(Calendars.VISIBLE, 1);
|
values.put(Calendars.VISIBLE, 1);
|
||||||
@ -196,7 +200,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
/* 8 */ Events.STATUS, Events.ACCESS_LEVEL,
|
/* 8 */ Events.STATUS, Events.ACCESS_LEVEL,
|
||||||
/* 10 */ Events.RRULE, Events.RDATE, Events.EXRULE, Events.EXDATE,
|
/* 10 */ Events.RRULE, Events.RDATE, Events.EXRULE, Events.EXDATE,
|
||||||
/* 14 */ Events.HAS_ATTENDEE_DATA, Events.ORGANIZER, Events.SELF_ATTENDEE_STATUS,
|
/* 14 */ Events.HAS_ATTENDEE_DATA, Events.ORGANIZER, Events.SELF_ATTENDEE_STATUS,
|
||||||
/* 17 */ entryColumnUID(), Events.DURATION
|
/* 17 */ entryColumnUID(), Events.DURATION, Events.AVAILABILITY
|
||||||
}, null, null, null);
|
}, null, null, null);
|
||||||
if (cursor != null && cursor.moveToNext()) {
|
if (cursor != null && cursor.moveToNext()) {
|
||||||
e.setUid(cursor.getString(17));
|
e.setUid(cursor.getString(17));
|
||||||
@ -270,12 +274,15 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
e.setStatus(Status.VEVENT_CANCELLED);
|
e.setStatus(Status.VEVENT_CANCELLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// availability
|
||||||
|
e.setOpaque(cursor.getInt(19) != Events.AVAILABILITY_FREE);
|
||||||
|
|
||||||
// attendees
|
// attendees
|
||||||
if (cursor.getInt(14) != 0) { // has attendees
|
if (cursor.getInt(14) != 0) { // has attendees
|
||||||
try {
|
try {
|
||||||
e.setOrganizer(new Organizer("mailto:" + cursor.getString(15)));
|
e.setOrganizer(new Organizer(new URI("mailto", cursor.getString(15), null)));
|
||||||
} catch (URISyntaxException ex) {
|
} catch (URISyntaxException ex) {
|
||||||
Log.e(TAG, "Error parsing organizer URI, ignoring");
|
Log.e(TAG, "Error when creating ORGANIZER URI, ignoring", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri attendeesUri = Attendees.CONTENT_URI.buildUpon()
|
Uri attendeesUri = Attendees.CONTENT_URI.buildUpon()
|
||||||
@ -287,7 +294,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
}, Attendees.EVENT_ID + "=?", new String[] { String.valueOf(e.getLocalID()) }, null);
|
}, Attendees.EVENT_ID + "=?", new String[] { String.valueOf(e.getLocalID()) }, null);
|
||||||
while (c != null && c.moveToNext()) {
|
while (c != null && c.moveToNext()) {
|
||||||
try {
|
try {
|
||||||
Attendee attendee = new Attendee("mailto:" + c.getString(0));
|
Attendee attendee = new Attendee(new URI("mailto", c.getString(0), null));
|
||||||
ParameterList params = attendee.getParameters();
|
ParameterList params = attendee.getParameters();
|
||||||
|
|
||||||
String cn = c.getString(1);
|
String cn = c.getString(1);
|
||||||
@ -314,13 +321,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// status
|
// status
|
||||||
int status = Attendees.ATTENDEE_STATUS_NONE;
|
switch (c.getInt(4)) {
|
||||||
if (relationship == Attendees.RELATIONSHIP_ORGANIZER) // we are organizer
|
|
||||||
status = cursor.getInt(16);
|
|
||||||
else
|
|
||||||
status = c.getInt(4);
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case Attendees.ATTENDEE_STATUS_INVITED:
|
case Attendees.ATTENDEE_STATUS_INVITED:
|
||||||
params.add(PartStat.NEEDS_ACTION);
|
params.add(PartStat.NEEDS_ACTION);
|
||||||
break;
|
break;
|
||||||
@ -337,7 +338,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
|
|
||||||
e.addAttendee(attendee);
|
e.addAttendee(attendee);
|
||||||
} catch (URISyntaxException ex) {
|
} catch (URISyntaxException ex) {
|
||||||
Log.e(TAG, "Couldn't parse attendee member URI, ignoring member");
|
Log.e(TAG, "Couldn't parse attendee information, ignoring", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,7 +430,10 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
.withValue(Events.ALL_DAY, event.isAllDay() ? 1 : 0)
|
.withValue(Events.ALL_DAY, event.isAllDay() ? 1 : 0)
|
||||||
.withValue(Events.DTSTART, event.getDtStartInMillis())
|
.withValue(Events.DTSTART, event.getDtStartInMillis())
|
||||||
.withValue(Events.EVENT_TIMEZONE, event.getDtStartTzID())
|
.withValue(Events.EVENT_TIMEZONE, event.getDtStartTzID())
|
||||||
.withValue(Events.HAS_ATTENDEE_DATA, event.getAttendees().isEmpty() ? 0 : 1);
|
.withValue(Events.HAS_ATTENDEE_DATA, event.getAttendees().isEmpty() ? 0 : 1)
|
||||||
|
.withValue(Events.GUESTS_CAN_INVITE_OTHERS, 1)
|
||||||
|
.withValue(Events.GUESTS_CAN_MODIFY, 1)
|
||||||
|
.withValue(Events.GUESTS_CAN_SEE_GUESTS, 1);
|
||||||
|
|
||||||
boolean recurring = false;
|
boolean recurring = false;
|
||||||
if (event.getRrule() != null) {
|
if (event.getRrule() != null) {
|
||||||
@ -478,6 +482,12 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
if (event.getDescription() != null)
|
if (event.getDescription() != null)
|
||||||
builder = builder.withValue(Events.DESCRIPTION, event.getDescription());
|
builder = builder.withValue(Events.DESCRIPTION, event.getDescription());
|
||||||
|
|
||||||
|
if (event.getOrganizer() != null && event.getOrganizer().getCalAddress() != null) {
|
||||||
|
URI organizer = event.getOrganizer().getCalAddress();
|
||||||
|
if (organizer.getScheme().equalsIgnoreCase("mailto"))
|
||||||
|
builder = builder.withValue(Events.ORGANIZER, organizer.getSchemeSpecificPart());
|
||||||
|
}
|
||||||
|
|
||||||
Status status = event.getStatus();
|
Status status = event.getStatus();
|
||||||
if (status != null) {
|
if (status != null) {
|
||||||
int statusCode = Events.STATUS_TENTATIVE;
|
int statusCode = Events.STATUS_TENTATIVE;
|
||||||
@ -488,6 +498,8 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
builder = builder.withValue(Events.STATUS, statusCode);
|
builder = builder.withValue(Events.STATUS, statusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder = builder.withValue(Events.AVAILABILITY, event.isOpaque() ? Events.AVAILABILITY_BUSY : Events.AVAILABILITY_FREE);
|
||||||
|
|
||||||
if (event.getForPublic() != null)
|
if (event.getForPublic() != null)
|
||||||
builder = builder.withValue(Events.ACCESS_LEVEL, event.getForPublic() ? Events.ACCESS_PUBLIC : Events.ACCESS_PRIVATE);
|
builder = builder.withValue(Events.ACCESS_LEVEL, event.getForPublic() ? Events.ACCESS_PUBLIC : Events.ACCESS_PRIVATE);
|
||||||
|
|
||||||
@ -547,7 +559,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
|
|
||||||
int status = Attendees.ATTENDEE_STATUS_NONE;
|
int status = Attendees.ATTENDEE_STATUS_NONE;
|
||||||
PartStat partStat = (PartStat)attendee.getParameter(Parameter.PARTSTAT);
|
PartStat partStat = (PartStat)attendee.getParameter(Parameter.PARTSTAT);
|
||||||
if (partStat == PartStat.NEEDS_ACTION)
|
if (partStat == null || partStat == PartStat.NEEDS_ACTION)
|
||||||
status = Attendees.ATTENDEE_STATUS_INVITED;
|
status = Attendees.ATTENDEE_STATUS_INVITED;
|
||||||
else if (partStat == PartStat.ACCEPTED)
|
else if (partStat == PartStat.ACCEPTED)
|
||||||
status = Attendees.ATTENDEE_STATUS_ACCEPTED;
|
status = Attendees.ATTENDEE_STATUS_ACCEPTED;
|
||||||
|
@ -9,7 +9,6 @@ package at.bitfire.davdroid.resource;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import net.fortuna.ical4j.model.ValidationException;
|
import net.fortuna.ical4j.model.ValidationException;
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
@ -23,6 +22,7 @@ import android.net.Uri;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import at.bitfire.davdroid.syncadapter.DavSyncAdapter;
|
||||||
|
|
||||||
public abstract class LocalCollection<T extends Resource> {
|
public abstract class LocalCollection<T extends Resource> {
|
||||||
private static final String TAG = "davdroid.LocalCollection";
|
private static final String TAG = "davdroid.LocalCollection";
|
||||||
@ -100,9 +100,9 @@ public abstract class LocalCollection<T extends Resource> {
|
|||||||
where, null, null);
|
where, null, null);
|
||||||
LinkedList<T> fresh = new LinkedList<T>();
|
LinkedList<T> fresh = new LinkedList<T>();
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
String uid = UUID.randomUUID().toString(),
|
String uid = DavSyncAdapter.generateUID(),
|
||||||
resourceName = uid + fileExtension();
|
resourceName = uid.replace("@", "_") + fileExtension();
|
||||||
T resource = findById(cursor.getLong(0), resourceName, null, true); //new Event(cursor.getLong(0), resourceName, null);
|
T resource = findById(cursor.getLong(0), resourceName, null, true);
|
||||||
resource.setUid(uid);
|
resource.setUid(uid);
|
||||||
|
|
||||||
// new record: set generated resource name in database
|
// new record: set generated resource name in database
|
||||||
|
@ -10,11 +10,11 @@ package at.bitfire.davdroid.resource;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import net.fortuna.ical4j.data.ParserException;
|
|
||||||
import net.fortuna.ical4j.model.ValidationException;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
import net.fortuna.ical4j.data.ParserException;
|
||||||
|
import net.fortuna.ical4j.model.ValidationException;
|
||||||
|
|
||||||
@ToString
|
@ToString
|
||||||
public abstract class Resource {
|
public abstract class Resource {
|
||||||
|
143
src/at/bitfire/davdroid/syncadapter/AccountDetailsFragment.java
Normal file
143
src/at/bitfire/davdroid/syncadapter/AccountDetailsFragment.java
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package at.bitfire.davdroid.syncadapter;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.provider.CalendarContract;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import at.bitfire.davdroid.Constants;
|
||||||
|
import at.bitfire.davdroid.R;
|
||||||
|
import at.bitfire.davdroid.resource.LocalCalendar;
|
||||||
|
|
||||||
|
public class AccountDetailsFragment extends Fragment implements TextWatcher {
|
||||||
|
public static final String KEY_SERVER_INFO = "server_info";
|
||||||
|
|
||||||
|
ServerInfo serverInfo;
|
||||||
|
|
||||||
|
EditText editAccountName;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View v = inflater.inflate(R.layout.account_details, container, false);
|
||||||
|
|
||||||
|
serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO);
|
||||||
|
|
||||||
|
editAccountName = (EditText)v.findViewById(R.id.account_name);
|
||||||
|
editAccountName.addTextChangedListener(this);
|
||||||
|
|
||||||
|
TextView textAccountNameInfo = (TextView)v.findViewById(R.id.account_name_info);
|
||||||
|
if (!serverInfo.hasEnabledCalendars())
|
||||||
|
textAccountNameInfo.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.account_details, menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.add_account:
|
||||||
|
addAccount();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// actions
|
||||||
|
|
||||||
|
void addAccount() {
|
||||||
|
ServerInfo serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO);
|
||||||
|
try {
|
||||||
|
String accountName = editAccountName.getText().toString();
|
||||||
|
|
||||||
|
AccountManager accountManager = AccountManager.get(getActivity());
|
||||||
|
Account account = new Account(accountName, Constants.ACCOUNT_TYPE);
|
||||||
|
Bundle userData = new Bundle();
|
||||||
|
userData.putString(Constants.ACCOUNT_KEY_BASE_URL, serverInfo.getBaseURL());
|
||||||
|
userData.putString(Constants.ACCOUNT_KEY_USERNAME, serverInfo.getUserName());
|
||||||
|
userData.putString(Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE, Boolean.toString(serverInfo.isAuthPreemptive()));
|
||||||
|
|
||||||
|
boolean syncContacts = false;
|
||||||
|
for (ServerInfo.ResourceInfo addressBook : serverInfo.getAddressBooks())
|
||||||
|
if (addressBook.isEnabled()) {
|
||||||
|
userData.putString(Constants.ACCOUNT_KEY_ADDRESSBOOK_PATH, addressBook.getPath());
|
||||||
|
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
||||||
|
syncContacts = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (syncContacts) {
|
||||||
|
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
||||||
|
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
|
||||||
|
} else
|
||||||
|
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
|
||||||
|
|
||||||
|
if (accountManager.addAccountExplicitly(account, serverInfo.getPassword(), userData)) {
|
||||||
|
// account created, now create calendars
|
||||||
|
boolean syncCalendars = false;
|
||||||
|
for (ServerInfo.ResourceInfo calendar : serverInfo.getCalendars())
|
||||||
|
if (calendar.isEnabled()) {
|
||||||
|
LocalCalendar.create(account, getActivity().getContentResolver(), calendar);
|
||||||
|
syncCalendars = true;
|
||||||
|
}
|
||||||
|
if (syncCalendars) {
|
||||||
|
ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 1);
|
||||||
|
ContentResolver.setSyncAutomatically(account, CalendarContract.AUTHORITY, true);
|
||||||
|
} else
|
||||||
|
ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 0);
|
||||||
|
|
||||||
|
getActivity().finish();
|
||||||
|
} else
|
||||||
|
Toast.makeText(getActivity(), "Couldn't create account (account with this name already existing?)", Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// input validation
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
|
boolean ok = false;
|
||||||
|
ok = editAccountName.getText().length() > 0;
|
||||||
|
MenuItem item = menu.findItem(R.id.add_account);
|
||||||
|
item.setEnabled(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
getActivity().invalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,9 @@ package at.bitfire.davdroid.syncadapter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.fortuna.ical4j.util.SimpleHostInfo;
|
||||||
|
import net.fortuna.ical4j.util.UidGenerator;
|
||||||
|
|
||||||
import org.apache.http.HttpException;
|
import org.apache.http.HttpException;
|
||||||
import org.apache.http.auth.AuthenticationException;
|
import org.apache.http.auth.AuthenticationException;
|
||||||
|
|
||||||
@ -16,6 +19,7 @@ import android.content.OperationApplicationException;
|
|||||||
import android.content.SyncResult;
|
import android.content.SyncResult;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import at.bitfire.davdroid.resource.LocalCollection;
|
import at.bitfire.davdroid.resource.LocalCollection;
|
||||||
import at.bitfire.davdroid.resource.RemoteCollection;
|
import at.bitfire.davdroid.resource.RemoteCollection;
|
||||||
@ -26,13 +30,25 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
|
|
||||||
protected AccountManager accountManager;
|
protected AccountManager accountManager;
|
||||||
|
|
||||||
|
private static String androidID;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public DavSyncAdapter(Context context) {
|
public DavSyncAdapter(Context context) {
|
||||||
super(context, true);
|
super(context, true);
|
||||||
|
|
||||||
|
androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||||
|
|
||||||
accountManager = AccountManager.get(context);
|
accountManager = AccountManager.get(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String generateUID() {
|
||||||
|
UidGenerator generator = new UidGenerator(new SimpleHostInfo(androidID), String.valueOf(android.os.Process.myPid()));
|
||||||
|
return generator.generateUid().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected abstract Map<LocalCollection<?>, RemoteCollection<?>> getSyncPairs(Account account, ContentProviderClient provider);
|
protected abstract Map<LocalCollection<?>, RemoteCollection<?>> getSyncPairs(Account account, ContentProviderClient provider);
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package at.bitfire.davdroid.syncadapter;
|
package at.bitfire.davdroid.syncadapter;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
import android.app.DialogFragment;
|
import android.app.DialogFragment;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
@ -38,11 +41,6 @@ public class EnterCredentialsFragment extends Fragment implements TextWatcher {
|
|||||||
Button btnNext;
|
Button btnNext;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View v = inflater.inflate(R.layout.enter_credentials, container, false);
|
View v = inflater.inflate(R.layout.enter_credentials, container, false);
|
||||||
@ -103,10 +101,9 @@ public class EnterCredentialsFragment extends Fragment implements TextWatcher {
|
|||||||
void queryServer() {
|
void queryServer() {
|
||||||
FragmentTransaction ft = getFragmentManager().beginTransaction();
|
FragmentTransaction ft = getFragmentManager().beginTransaction();
|
||||||
|
|
||||||
String host_path = editBaseURL.getText().toString();
|
|
||||||
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
||||||
|
String host_path = editBaseURL.getText().toString();
|
||||||
args.putString(QueryServerDialogFragment.EXTRA_BASE_URL, URIUtils.sanitize(protocol + host_path));
|
args.putString(QueryServerDialogFragment.EXTRA_BASE_URL, URIUtils.sanitize(protocol + host_path));
|
||||||
args.putString(QueryServerDialogFragment.EXTRA_USER_NAME, editUserName.getText().toString());
|
args.putString(QueryServerDialogFragment.EXTRA_USER_NAME, editUserName.getText().toString());
|
||||||
args.putString(QueryServerDialogFragment.EXTRA_PASSWORD, editPassword.getText().toString());
|
args.putString(QueryServerDialogFragment.EXTRA_PASSWORD, editPassword.getText().toString());
|
||||||
@ -118,16 +115,23 @@ public class EnterCredentialsFragment extends Fragment implements TextWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// form validation
|
// input validation
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
boolean ok =
|
boolean ok =
|
||||||
editBaseURL.getText().length() > 0 &&
|
|
||||||
!editBaseURL.getText().toString().startsWith("/") && // host name required
|
|
||||||
editUserName.getText().length() > 0 &&
|
editUserName.getText().length() > 0 &&
|
||||||
editPassword.getText().length() > 0;
|
editPassword.getText().length() > 0;
|
||||||
|
|
||||||
|
// check host name
|
||||||
|
try {
|
||||||
|
URL url = new URL(protocol + editBaseURL.getText().toString());
|
||||||
|
if (url.getHost() == null || url.getHost().isEmpty())
|
||||||
|
ok = false;
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
MenuItem item = menu.findItem(R.id.next);
|
MenuItem item = menu.findItem(R.id.next);
|
||||||
item.setEnabled(ok);
|
item.setEnabled(ok);
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,8 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package at.bitfire.davdroid.syncadapter;
|
package at.bitfire.davdroid.syncadapter;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.accounts.AccountManager;
|
|
||||||
import android.app.ListFragment;
|
import android.app.ListFragment;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.provider.CalendarContract;
|
|
||||||
import android.provider.ContactsContract;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@ -30,10 +19,7 @@ import android.widget.AdapterView;
|
|||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
import android.widget.ListAdapter;
|
import android.widget.ListAdapter;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.Toast;
|
|
||||||
import at.bitfire.davdroid.Constants;
|
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
import at.bitfire.davdroid.resource.LocalCalendar;
|
|
||||||
|
|
||||||
public class SelectCollectionsFragment extends ListFragment {
|
public class SelectCollectionsFragment extends ListFragment {
|
||||||
public static final String KEY_SERVER_INFO = "server_info";
|
public static final String KEY_SERVER_INFO = "server_info";
|
||||||
@ -45,6 +31,12 @@ public class SelectCollectionsFragment extends ListFragment {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
setListAdapter(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
@ -84,8 +76,32 @@ public class SelectCollectionsFragment extends ListFragment {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.add_account:
|
case R.id.next:
|
||||||
addAccount();
|
ServerInfo serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO);
|
||||||
|
|
||||||
|
// synchronize only selected collections
|
||||||
|
for (ServerInfo.ResourceInfo addressBook : serverInfo.getAddressBooks())
|
||||||
|
addressBook.setEnabled(false);
|
||||||
|
for (ServerInfo.ResourceInfo calendar : serverInfo.getCalendars())
|
||||||
|
calendar.setEnabled(false);
|
||||||
|
|
||||||
|
ListAdapter adapter = getListView().getAdapter();
|
||||||
|
for (long id : getListView().getCheckedItemIds()) {
|
||||||
|
int position = (int)id + 1; // +1 because header view is inserted at pos. 0
|
||||||
|
ServerInfo.ResourceInfo info = (ServerInfo.ResourceInfo)adapter.getItem(position);
|
||||||
|
info.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass to "account details" fragment
|
||||||
|
AccountDetailsFragment accountDetails = new AccountDetailsFragment();
|
||||||
|
Bundle arguments = new Bundle();
|
||||||
|
arguments.putSerializable(SelectCollectionsFragment.KEY_SERVER_INFO, serverInfo);
|
||||||
|
accountDetails.setArguments(arguments);
|
||||||
|
|
||||||
|
getFragmentManager().beginTransaction()
|
||||||
|
.replace(R.id.fragment_container, accountDetails)
|
||||||
|
.addToBackStack(null)
|
||||||
|
.commitAllowingStateLoss();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -94,7 +110,7 @@ public class SelectCollectionsFragment extends ListFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// form validation
|
// input validation
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
@ -103,65 +119,7 @@ public class SelectCollectionsFragment extends ListFragment {
|
|||||||
ok = getListView().getCheckedItemCount() > 0;
|
ok = getListView().getCheckedItemCount() > 0;
|
||||||
} catch(IllegalStateException e) {
|
} catch(IllegalStateException e) {
|
||||||
}
|
}
|
||||||
MenuItem item = menu.findItem(R.id.add_account);
|
MenuItem item = menu.findItem(R.id.next);
|
||||||
item.setEnabled(ok);
|
item.setEnabled(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// actions
|
|
||||||
|
|
||||||
void addAccount() {
|
|
||||||
List<ServerInfo.ResourceInfo> addressBooks = new LinkedList<ServerInfo.ResourceInfo>(),
|
|
||||||
calendars = new LinkedList<ServerInfo.ResourceInfo>();
|
|
||||||
|
|
||||||
ListAdapter adapter = getListView().getAdapter();
|
|
||||||
for (long id : getListView().getCheckedItemIds()) {
|
|
||||||
int position = (int)id + 1; // +1 because header view is inserted at pos. 0
|
|
||||||
ServerInfo.ResourceInfo info = (ServerInfo.ResourceInfo)adapter.getItem(position);
|
|
||||||
switch (info.getType()) {
|
|
||||||
case ADDRESS_BOOK:
|
|
||||||
addressBooks.add(info);
|
|
||||||
break;
|
|
||||||
case CALENDAR:
|
|
||||||
calendars.add(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerInfo serverInfo = (ServerInfo)getArguments().getSerializable(KEY_SERVER_INFO);
|
|
||||||
try {
|
|
||||||
URI baseURI = new URI(serverInfo.getBaseURL());
|
|
||||||
String accountName = serverInfo.getUserName() + "@" + baseURI.getHost() + baseURI.getPath();
|
|
||||||
|
|
||||||
AccountManager accountManager = AccountManager.get(getActivity());
|
|
||||||
Account account = new Account(accountName, Constants.ACCOUNT_TYPE);
|
|
||||||
Bundle userData = new Bundle();
|
|
||||||
userData.putString(Constants.ACCOUNT_KEY_BASE_URL, serverInfo.getBaseURL());
|
|
||||||
userData.putString(Constants.ACCOUNT_KEY_USERNAME, serverInfo.getUserName());
|
|
||||||
userData.putString(Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE, Boolean.toString(serverInfo.isAuthPreemptive()));
|
|
||||||
|
|
||||||
if (!addressBooks.isEmpty()) {
|
|
||||||
userData.putString(Constants.ACCOUNT_KEY_ADDRESSBOOK_PATH, addressBooks.get(0).getPath());
|
|
||||||
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
|
||||||
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
|
|
||||||
} else
|
|
||||||
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 0);
|
|
||||||
|
|
||||||
if (accountManager.addAccountExplicitly(account, serverInfo.getPassword(), userData)) {
|
|
||||||
// account created, now create calendars
|
|
||||||
if (!calendars.isEmpty()) {
|
|
||||||
for (ServerInfo.ResourceInfo calendar : calendars)
|
|
||||||
LocalCalendar.create(account, getActivity().getContentResolver(), calendar);
|
|
||||||
ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 1);
|
|
||||||
ContentResolver.setSyncAutomatically(account, CalendarContract.AUTHORITY, true);
|
|
||||||
} else
|
|
||||||
ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 0);
|
|
||||||
|
|
||||||
getActivity().finish();
|
|
||||||
} else
|
|
||||||
Toast.makeText(getActivity(), "Couldn't create account (already existing?)", Toast.LENGTH_LONG).show();
|
|
||||||
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
package at.bitfire.davdroid.syncadapter;
|
package at.bitfire.davdroid.syncadapter;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -25,7 +26,17 @@ public class ServerInfo implements Serializable {
|
|||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
|
|
||||||
private boolean calDAV, cardDAV;
|
private boolean calDAV, cardDAV;
|
||||||
private List<ResourceInfo> addressBooks, calendars;
|
private List<ResourceInfo>
|
||||||
|
addressBooks = new LinkedList<ResourceInfo>(),
|
||||||
|
calendars = new LinkedList<ResourceInfo>();
|
||||||
|
|
||||||
|
public boolean hasEnabledCalendars() {
|
||||||
|
for (ResourceInfo calendar : calendars)
|
||||||
|
if (calendar.enabled)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequiredArgsConstructor(suppressConstructorProperties=true)
|
@RequiredArgsConstructor(suppressConstructorProperties=true)
|
||||||
@Data
|
@Data
|
||||||
@ -37,6 +48,8 @@ public class ServerInfo implements Serializable {
|
|||||||
CALENDAR
|
CALENDAR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean enabled = false;
|
||||||
|
|
||||||
final Type type;
|
final Type type;
|
||||||
final String path, title, description, color;
|
final String path, title, description, color;
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ package at.bitfire.davdroid.test;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
|
||||||
import net.fortuna.ical4j.data.ParserException;
|
import net.fortuna.ical4j.data.ParserException;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.test.InstrumentationTestCase;
|
import android.test.InstrumentationTestCase;
|
||||||
@ -26,10 +25,11 @@ public class CalendarTest extends InstrumentationTestCase {
|
|||||||
|
|
||||||
public void testTimeZonesByEvolution() throws IOException, ParserException {
|
public void testTimeZonesByEvolution() throws IOException, ParserException {
|
||||||
Event e = parseCalendar("vienna-evolution.ics");
|
Event e = parseCalendar("vienna-evolution.ics");
|
||||||
Assert.assertEquals("Test-Ereignis im schönen Wien", e.getSummary());
|
assertEquals("Test-Ereignis im schönen Wien", e.getSummary());
|
||||||
|
|
||||||
//DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Vienna:20131009T170000
|
//DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Vienna:20131009T170000
|
||||||
Assert.assertEquals(1381327200, e.getDtStartInMillis());
|
/*assertEquals(1381330800000L, e.getDtStartInMillis());
|
||||||
|
assertEquals(1381334400000L, (long)e.getDtEndInMillis());*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user