mirror of
https://github.com/etesync/android
synced 2024-11-26 01:48:34 +00:00
Resource detection, bug fixes
* resource detection is subject to change yet * don't use UID_2445 for Android <= 4.1 * more useful sync error notification messages * handle 401 Unauthorized and show account info when notification is tapped
This commit is contained in:
parent
f344bd3c28
commit
20bc5af4a3
@ -126,8 +126,9 @@ public class HttpClient extends OkHttpClient {
|
|||||||
// add User-Agent to every request
|
// add User-Agent to every request
|
||||||
networkInterceptors().add(userAgentInterceptor);
|
networkInterceptors().add(userAgentInterceptor);
|
||||||
|
|
||||||
// enable logs
|
// enable verbose logs, if requested
|
||||||
enableLogs();
|
if (Constants.log.isTraceEnabled())
|
||||||
|
enableLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void enableLogs() {
|
protected void enableLogs() {
|
||||||
|
@ -58,117 +58,126 @@ public class DavResourceFinder {
|
|||||||
final HttpClient httpClient = new HttpClient(context, serverInfo.getUserName(), serverInfo.getPassword(), serverInfo.authPreemptive);
|
final HttpClient httpClient = new HttpClient(context, serverInfo.getUserName(), serverInfo.getPassword(), serverInfo.authPreemptive);
|
||||||
|
|
||||||
// CardDAV
|
// CardDAV
|
||||||
Constants.log.info("*** CardDAV resource detection ***");
|
try {
|
||||||
HttpUrl principalUrl = getCurrentUserPrincipal(httpClient, serverInfo, "carddav");
|
Constants.log.info("*** CardDAV resource detection ***");
|
||||||
|
HttpUrl principalUrl = getCurrentUserPrincipal(httpClient, serverInfo, "carddav");
|
||||||
|
|
||||||
DavResource principal = new DavResource(httpClient, principalUrl);
|
DavResource principal = new DavResource(httpClient, principalUrl);
|
||||||
principal.propfind(0, AddressbookHomeSet.NAME);
|
principal.propfind(0, AddressbookHomeSet.NAME);
|
||||||
AddressbookHomeSet addrHomeSet = (AddressbookHomeSet)principal.properties.get(AddressbookHomeSet.NAME);
|
AddressbookHomeSet addrHomeSet = (AddressbookHomeSet) principal.properties.get(AddressbookHomeSet.NAME);
|
||||||
if (addrHomeSet != null && !addrHomeSet.hrefs.isEmpty()) {
|
if (addrHomeSet != null && !addrHomeSet.hrefs.isEmpty()) {
|
||||||
Constants.log.info("Found addressbook home set(s): " + addrHomeSet);
|
Constants.log.info("Found addressbook home set(s): " + addrHomeSet);
|
||||||
|
|
||||||
// enumerate address books
|
// enumerate address books
|
||||||
List<ServerInfo.ResourceInfo> addressBooks = new LinkedList<>();
|
List<ServerInfo.ResourceInfo> addressBooks = new LinkedList<>();
|
||||||
for (String href : addrHomeSet.hrefs) {
|
for (String href : addrHomeSet.hrefs) {
|
||||||
DavResource homeSet = new DavResource(httpClient, principalUrl.resolve(href));
|
DavResource homeSet = new DavResource(httpClient, principalUrl.resolve(href));
|
||||||
homeSet.propfind(1, ResourceType.NAME, CurrentUserPrivilegeSet.NAME, DisplayName.NAME, AddressbookDescription.NAME);
|
homeSet.propfind(1, ResourceType.NAME, CurrentUserPrivilegeSet.NAME, DisplayName.NAME, AddressbookDescription.NAME);
|
||||||
for (DavResource member : homeSet.members) {
|
for (DavResource member : homeSet.members) {
|
||||||
ResourceType type = (ResourceType)member.properties.get(ResourceType.NAME);
|
ResourceType type = (ResourceType) member.properties.get(ResourceType.NAME);
|
||||||
if (type != null && type.types.contains(ResourceType.ADDRESSBOOK)) {
|
if (type != null && type.types.contains(ResourceType.ADDRESSBOOK)) {
|
||||||
Constants.log.info("Found address book: " + member.location);
|
Constants.log.info("Found address book: " + member.location);
|
||||||
|
|
||||||
CurrentUserPrivilegeSet privs = (CurrentUserPrivilegeSet)member.properties.get(CurrentUserPrivilegeSet.NAME);
|
CurrentUserPrivilegeSet privs = (CurrentUserPrivilegeSet) member.properties.get(CurrentUserPrivilegeSet.NAME);
|
||||||
if (privs != null && (!privs.mayRead || !privs.mayWriteContent)) {
|
if (privs != null && (!privs.mayRead || !privs.mayWriteContent)) {
|
||||||
Constants.log.info("Only read/write address books are supported, ignoring this one");
|
Constants.log.info("Only read/write address books are supported, ignoring this one");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayName displayName = (DisplayName) member.properties.get(DisplayName.NAME);
|
||||||
|
AddressbookDescription description = (AddressbookDescription) member.properties.get(AddressbookDescription.NAME);
|
||||||
|
|
||||||
|
addressBooks.add(new ServerInfo.ResourceInfo(
|
||||||
|
ServerInfo.ResourceInfo.Type.ADDRESS_BOOK,
|
||||||
|
false,
|
||||||
|
member.location.toString(),
|
||||||
|
displayName != null ? displayName.displayName : null,
|
||||||
|
description != null ? description.description : null,
|
||||||
|
null
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayName displayName = (DisplayName)member.properties.get(DisplayName.NAME);
|
|
||||||
AddressbookDescription description = (AddressbookDescription)member.properties.get(AddressbookDescription.NAME);
|
|
||||||
|
|
||||||
addressBooks.add(new ServerInfo.ResourceInfo(
|
|
||||||
ServerInfo.ResourceInfo.Type.ADDRESS_BOOK,
|
|
||||||
false,
|
|
||||||
member.location.toString(),
|
|
||||||
displayName != null ? displayName.displayName : null,
|
|
||||||
description != null ? description.description : null,
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
serverInfo.setAddressBooks(addressBooks);
|
||||||
}
|
}
|
||||||
serverInfo.setAddressBooks(addressBooks);
|
} catch(IOException|HttpException|DavException e) {
|
||||||
|
Constants.log.info("CardDAV detection failed", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalDAV
|
// CalDAV
|
||||||
Constants.log.info("*** CalDAV resource detection ***");
|
Constants.log.info("*** CalDAV resource detection ***");
|
||||||
principalUrl = getCurrentUserPrincipal(httpClient, serverInfo, "caldav");
|
try {
|
||||||
|
HttpUrl principalUrl = getCurrentUserPrincipal(httpClient, serverInfo, "caldav");
|
||||||
|
|
||||||
principal = new DavResource(httpClient, principalUrl);
|
DavResource principal = new DavResource(httpClient, principalUrl);
|
||||||
principal.propfind(0, CalendarHomeSet.NAME);
|
principal.propfind(0, CalendarHomeSet.NAME);
|
||||||
CalendarHomeSet calHomeSet = (CalendarHomeSet)principal.properties.get(CalendarHomeSet.NAME);
|
CalendarHomeSet calHomeSet = (CalendarHomeSet) principal.properties.get(CalendarHomeSet.NAME);
|
||||||
if (calHomeSet != null && !calHomeSet.hrefs.isEmpty()) {
|
if (calHomeSet != null && !calHomeSet.hrefs.isEmpty()) {
|
||||||
Constants.log.info("Found calendar home set(s): " + calHomeSet);
|
Constants.log.info("Found calendar home set(s): " + calHomeSet);
|
||||||
|
|
||||||
// enumerate address books
|
// enumerate address books
|
||||||
List<ServerInfo.ResourceInfo>
|
List<ServerInfo.ResourceInfo>
|
||||||
calendars = new LinkedList<>(),
|
calendars = new LinkedList<>(),
|
||||||
taskLists = new LinkedList<>();
|
taskLists = new LinkedList<>();
|
||||||
|
|
||||||
for (String href : calHomeSet.hrefs) {
|
for (String href : calHomeSet.hrefs) {
|
||||||
DavResource homeSet = new DavResource(httpClient, principalUrl.resolve(href));
|
DavResource homeSet = new DavResource(httpClient, principalUrl.resolve(href));
|
||||||
homeSet.propfind(1, ResourceType.NAME, CurrentUserPrivilegeSet.NAME, DisplayName.NAME,
|
homeSet.propfind(1, ResourceType.NAME, CurrentUserPrivilegeSet.NAME, DisplayName.NAME,
|
||||||
CalendarDescription.NAME, CalendarColor.NAME, CalendarTimezone.NAME, SupportedCalendarComponentSet.NAME);
|
CalendarDescription.NAME, CalendarColor.NAME, CalendarTimezone.NAME, SupportedCalendarComponentSet.NAME);
|
||||||
for (DavResource member : homeSet.members) {
|
for (DavResource member : homeSet.members) {
|
||||||
ResourceType type = (ResourceType)member.properties.get(ResourceType.NAME);
|
ResourceType type = (ResourceType) member.properties.get(ResourceType.NAME);
|
||||||
if (type != null && type.types.contains(ResourceType.CALENDAR)) {
|
if (type != null && type.types.contains(ResourceType.CALENDAR)) {
|
||||||
Constants.log.info("Found calendar: " + member.location);
|
Constants.log.info("Found calendar: " + member.location);
|
||||||
|
|
||||||
DisplayName displayName = (DisplayName)member.properties.get(DisplayName.NAME);
|
DisplayName displayName = (DisplayName) member.properties.get(DisplayName.NAME);
|
||||||
CalendarDescription description = (CalendarDescription)member.properties.get(CalendarDescription.NAME);
|
CalendarDescription description = (CalendarDescription) member.properties.get(CalendarDescription.NAME);
|
||||||
CalendarColor color = (CalendarColor)member.properties.get(CalendarColor.NAME);
|
CalendarColor color = (CalendarColor) member.properties.get(CalendarColor.NAME);
|
||||||
|
|
||||||
CurrentUserPrivilegeSet privs = (CurrentUserPrivilegeSet)member.properties.get(CurrentUserPrivilegeSet.NAME);
|
CurrentUserPrivilegeSet privs = (CurrentUserPrivilegeSet) member.properties.get(CurrentUserPrivilegeSet.NAME);
|
||||||
boolean readOnly = false;
|
boolean readOnly = false;
|
||||||
if (privs != null) {
|
if (privs != null) {
|
||||||
if (!privs.mayRead) {
|
if (!privs.mayRead) {
|
||||||
Constants.log.info("Calendar not readable, ignoring this one");
|
Constants.log.info("Calendar not readable, ignoring this one");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
readOnly = !privs.mayWriteContent;
|
||||||
}
|
}
|
||||||
readOnly = !privs.mayWriteContent;
|
|
||||||
|
ServerInfo.ResourceInfo collection = new ServerInfo.ResourceInfo(
|
||||||
|
ServerInfo.ResourceInfo.Type.ADDRESS_BOOK,
|
||||||
|
readOnly,
|
||||||
|
member.location.toString(),
|
||||||
|
displayName != null ? displayName.displayName : null,
|
||||||
|
description != null ? description.description : null,
|
||||||
|
color != null ? color.color : null
|
||||||
|
);
|
||||||
|
|
||||||
|
CalendarTimezone tz = (CalendarTimezone) member.properties.get(CalendarTimezone.NAME);
|
||||||
|
if (tz != null)
|
||||||
|
collection.timezone = tz.vTimeZone;
|
||||||
|
|
||||||
|
boolean isCalendar = true, isTaskList = true;
|
||||||
|
SupportedCalendarComponentSet comp = (SupportedCalendarComponentSet) member.properties.get(SupportedCalendarComponentSet.NAME);
|
||||||
|
if (comp != null) {
|
||||||
|
isCalendar = comp.supportsEvents;
|
||||||
|
isTaskList = comp.supportsTasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCalendar)
|
||||||
|
calendars.add(collection);
|
||||||
|
if (isTaskList)
|
||||||
|
taskLists.add(collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerInfo.ResourceInfo collection = new ServerInfo.ResourceInfo(
|
|
||||||
ServerInfo.ResourceInfo.Type.ADDRESS_BOOK,
|
|
||||||
readOnly,
|
|
||||||
member.location.toString(),
|
|
||||||
displayName != null ? displayName.displayName : null,
|
|
||||||
description != null ? description.description : null,
|
|
||||||
color != null ? color.color : null
|
|
||||||
);
|
|
||||||
|
|
||||||
CalendarTimezone tz = (CalendarTimezone)member.properties.get(CalendarTimezone.NAME);
|
|
||||||
if (tz != null)
|
|
||||||
collection.timezone = tz.vTimeZone;
|
|
||||||
|
|
||||||
boolean isCalendar = true, isTaskList = true;
|
|
||||||
SupportedCalendarComponentSet comp = (SupportedCalendarComponentSet)member.properties.get(SupportedCalendarComponentSet.NAME);
|
|
||||||
if (comp != null) {
|
|
||||||
isCalendar = comp.supportsEvents;
|
|
||||||
isTaskList = comp.supportsTasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCalendar)
|
|
||||||
calendars.add(collection);
|
|
||||||
if (isTaskList)
|
|
||||||
taskLists.add(collection);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
serverInfo.setCalendars(calendars);
|
||||||
|
serverInfo.setTaskLists(taskLists);
|
||||||
}
|
}
|
||||||
serverInfo.setCalendars(calendars);
|
} catch(IOException|HttpException|DavException e) {
|
||||||
serverInfo.setTaskLists(taskLists);
|
Constants.log.info("CalDAV detection failed", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
/*if (!serverInfo.isCalDAV() && !serverInfo.isCardDAV())
|
/*if (!serverInfo.isCalDAV() && !serverInfo.isCardDAV())
|
||||||
throw new DavIncapableException(context.getString(R.string.setup_neither_caldav_nor_carddav));*/
|
throw new DavIncapableException(context.getString(R.string.setup_neither_caldav_nor_carddav));*/
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ package at.bitfire.davdroid.resource;
|
|||||||
|
|
||||||
import android.content.ContentProviderOperation;
|
import android.content.ContentProviderOperation;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.provider.CalendarContract.Events;
|
import android.provider.CalendarContract.Events;
|
||||||
@ -32,8 +33,8 @@ public class LocalEvent extends AndroidEvent implements LocalResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static final String COLUMN_ETAG = CalendarContract.Events.SYNC_DATA1,
|
static final String COLUMN_ETAG = CalendarContract.Events.SYNC_DATA1,
|
||||||
COLUMN_UID = CalendarContract.Events.UID_2445,
|
COLUMN_UID = Build.VERSION.SDK_INT >= 17 ? Events.UID_2445 : Events.SYNC_DATA2,
|
||||||
COLUMN_SEQUENCE = CalendarContract.Events.SYNC_DATA2;
|
COLUMN_SEQUENCE = CalendarContract.Events.SYNC_DATA3;
|
||||||
|
|
||||||
@Getter protected String fileName;
|
@Getter protected String fileName;
|
||||||
@Getter @Setter protected String eTag;
|
@Getter @Setter protected String eTag;
|
||||||
|
@ -36,8 +36,8 @@ public class LocalTask extends AndroidTask implements LocalResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static final String COLUMN_ETAG = Tasks.SYNC1,
|
static final String COLUMN_ETAG = Tasks.SYNC1,
|
||||||
COLUMN_UID = Tasks._UID,
|
COLUMN_UID = Tasks.SYNC2,
|
||||||
COLUMN_SEQUENCE = Tasks.SYNC2;
|
COLUMN_SEQUENCE = Tasks.SYNC3;
|
||||||
|
|
||||||
@Getter protected String fileName;
|
@Getter protected String fileName;
|
||||||
@Getter @Setter protected String eTag;
|
@Getter @Setter protected String eTag;
|
||||||
|
@ -33,6 +33,7 @@ import java.util.UUID;
|
|||||||
import at.bitfire.dav4android.DavResource;
|
import at.bitfire.dav4android.DavResource;
|
||||||
import at.bitfire.dav4android.exception.DavException;
|
import at.bitfire.dav4android.exception.DavException;
|
||||||
import at.bitfire.dav4android.exception.HttpException;
|
import at.bitfire.dav4android.exception.HttpException;
|
||||||
|
import at.bitfire.dav4android.exception.UnauthorizedException;
|
||||||
import at.bitfire.dav4android.exception.PreconditionFailedException;
|
import at.bitfire.dav4android.exception.PreconditionFailedException;
|
||||||
import at.bitfire.dav4android.exception.ServiceUnavailableException;
|
import at.bitfire.dav4android.exception.ServiceUnavailableException;
|
||||||
import at.bitfire.dav4android.property.GetCTag;
|
import at.bitfire.dav4android.property.GetCTag;
|
||||||
@ -43,6 +44,7 @@ import at.bitfire.davdroid.R;
|
|||||||
import at.bitfire.davdroid.resource.LocalCollection;
|
import at.bitfire.davdroid.resource.LocalCollection;
|
||||||
import at.bitfire.davdroid.resource.LocalResource;
|
import at.bitfire.davdroid.resource.LocalResource;
|
||||||
import at.bitfire.davdroid.ui.DebugInfoActivity;
|
import at.bitfire.davdroid.ui.DebugInfoActivity;
|
||||||
|
import at.bitfire.davdroid.ui.settings.AccountActivity;
|
||||||
import at.bitfire.ical4android.CalendarStorageException;
|
import at.bitfire.ical4android.CalendarStorageException;
|
||||||
import at.bitfire.vcard4android.ContactsStorageException;
|
import at.bitfire.vcard4android.ContactsStorageException;
|
||||||
|
|
||||||
@ -165,18 +167,36 @@ abstract public class SyncManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
if (e instanceof HttpException || e instanceof DavException) {
|
final int messageString;
|
||||||
|
|
||||||
|
if (e instanceof UnauthorizedException) {
|
||||||
|
Constants.log.error("Not authorized anymore", e);
|
||||||
|
messageString = R.string.sync_error_unauthorized;
|
||||||
|
syncResult.stats.numAuthExceptions++;
|
||||||
|
} else if (e instanceof HttpException || e instanceof DavException) {
|
||||||
Constants.log.error("HTTP/DAV Exception during sync", e);
|
Constants.log.error("HTTP/DAV Exception during sync", e);
|
||||||
|
messageString = R.string.sync_error_http_dav;
|
||||||
syncResult.stats.numParseExceptions++;
|
syncResult.stats.numParseExceptions++;
|
||||||
} else if (e instanceof CalendarStorageException || e instanceof ContactsStorageException) {
|
} else if (e instanceof CalendarStorageException || e instanceof ContactsStorageException) {
|
||||||
Constants.log.error("Couldn't access local storage", e);
|
Constants.log.error("Couldn't access local storage", e);
|
||||||
|
messageString = R.string.sync_error_local_storage;
|
||||||
syncResult.databaseError = true;
|
syncResult.databaseError = true;
|
||||||
|
} else {
|
||||||
|
Constants.log.error("Unknown sync error", e);
|
||||||
|
messageString = R.string.sync_error;
|
||||||
|
syncResult.stats.numParseExceptions++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent detailsIntent = new Intent(context, DebugInfoActivity.class);
|
final Intent detailsIntent;
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_EXCEPTION, e);
|
if (e instanceof UnauthorizedException) {
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
detailsIntent = new Intent(context, AccountActivity.class);
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase);
|
detailsIntent.putExtra(AccountActivity.EXTRA_ACCOUNT, account);
|
||||||
|
} else {
|
||||||
|
detailsIntent = new Intent(context, DebugInfoActivity.class);
|
||||||
|
detailsIntent.putExtra(DebugInfoActivity.KEY_EXCEPTION, e);
|
||||||
|
detailsIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
||||||
|
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase);
|
||||||
|
}
|
||||||
|
|
||||||
Notification.Builder builder = new Notification.Builder(context);
|
Notification.Builder builder = new Notification.Builder(context);
|
||||||
Notification notification;
|
Notification notification;
|
||||||
@ -184,9 +204,13 @@ abstract public class SyncManager {
|
|||||||
.setContentTitle(context.getString(R.string.sync_error_title, account.name))
|
.setContentTitle(context.getString(R.string.sync_error_title, account.name))
|
||||||
.setContentIntent(PendingIntent.getActivity(context, 0, detailsIntent, PendingIntent.FLAG_UPDATE_CURRENT));
|
.setContentIntent(PendingIntent.getActivity(context, 0, detailsIntent, PendingIntent.FLAG_UPDATE_CURRENT));
|
||||||
|
|
||||||
String[] phases = context.getResources().getStringArray(R.array.sync_error_phases);
|
try {
|
||||||
if (phases.length > syncPhase)
|
String[] phases = context.getResources().getStringArray(R.array.sync_error_phases);
|
||||||
builder.setContentText(context.getString(R.string.sync_error_http, phases[syncPhase]));
|
String message = context.getString(messageString, phases[syncPhase]);
|
||||||
|
builder.setContentText(message);
|
||||||
|
} catch (IndexOutOfBoundsException ex) {
|
||||||
|
// should never happen
|
||||||
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 16) {
|
if (Build.VERSION.SDK_INT >= 16) {
|
||||||
if (Build.VERSION.SDK_INT >= 21)
|
if (Build.VERSION.SDK_INT >= 21)
|
||||||
|
@ -182,7 +182,7 @@ public class TasksSyncManager extends SyncManager {
|
|||||||
try {
|
try {
|
||||||
tasks = Task.fromStream(stream, charset);
|
tasks = Task.fromStream(stream, charset);
|
||||||
} catch (InvalidCalendarException e) {
|
} catch (InvalidCalendarException e) {
|
||||||
Constants.log.error("Received invalid iCalendar, ignoring");
|
Constants.log.error("Received invalid iCalendar, ignoring", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ public class TasksSyncManager extends SyncManager {
|
|||||||
syncResult.stats.numInserts++;
|
syncResult.stats.numInserts++;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
Constants.log.error("Received VCALENDAR with not exactly one VEVENT with UID, but without RECURRENCE-ID; ignoring " + fileName);
|
Constants.log.error("Received VCALENDAR with not exactly one VTODO; ignoring " + fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,10 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
|
||||||
@ -137,10 +141,7 @@ public class DebugInfoActivity extends Activity {
|
|||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
report.append("STACK TRACE\n");
|
report.append("STACK TRACE\n");
|
||||||
StringWriter writer = new StringWriter();
|
report.append(Throwables.getStackTraceAsString(exception));
|
||||||
@Cleanup PrintWriter printWriter = new PrintWriter(writer);
|
|
||||||
exception.printStackTrace(printWriter);
|
|
||||||
report.append(writer.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return report.toString();
|
return report.toString();
|
||||||
|
@ -178,7 +178,9 @@
|
|||||||
<string name="setup_read_only">schreibgeschützt</string>
|
<string name="setup_read_only">schreibgeschützt</string>
|
||||||
|
|
||||||
<string name="sync_error_title">Synchronisierung von %s fehlgeschlagen</string>
|
<string name="sync_error_title">Synchronisierung von %s fehlgeschlagen</string>
|
||||||
<string name="sync_error_http">HTTP-Fehler beim %1$s</string>
|
<string name="sync_error">Fehler beim %1$s</string>
|
||||||
|
<string name="sync_error_http_dav">Serverfehler</string>
|
||||||
|
<string name="sync_error_local_storage">Datenbank-Fehler</string>
|
||||||
<string-array name="sync_error_phases">
|
<string-array name="sync_error_phases">
|
||||||
<item>Vorbereiten der Synchronisierung</item>
|
<item>Vorbereiten der Synchronisierung</item>
|
||||||
<item>Abfragen der Server-Fähigkeiten</item>
|
<item>Abfragen der Server-Fähigkeiten</item>
|
||||||
@ -188,8 +190,10 @@
|
|||||||
<item>Abfragen des Synchronisierungs-Zustands</item>
|
<item>Abfragen des Synchronisierungs-Zustands</item>
|
||||||
<item>Auflisten lokaler Einträge</item>
|
<item>Auflisten lokaler Einträge</item>
|
||||||
<item>Auflisten der Server-Einträge</item>
|
<item>Auflisten der Server-Einträge</item>
|
||||||
|
<item>Vergleichen tw. Datenbank/Server</item>
|
||||||
<item>Herunterladen von Server-Einträgen</item>
|
<item>Herunterladen von Server-Einträgen</item>
|
||||||
<item>Speichern des Synchronisierungs-Zustands</item>
|
<item>Speichern des Synchronisierungs-Zustands</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string name="sync_error_unauthorized">Benutzername/Passwort falsch</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
@ -193,7 +193,9 @@
|
|||||||
<!-- sync errors and DebugInfoActivity -->
|
<!-- sync errors and DebugInfoActivity -->
|
||||||
<string name="debug_info_title">Debug info</string>
|
<string name="debug_info_title">Debug info</string>
|
||||||
<string name="sync_error_title">Synchronization of %s failed</string>
|
<string name="sync_error_title">Synchronization of %s failed</string>
|
||||||
<string name="sync_error_http">HTTP error while %1$s</string>
|
<string name="sync_error">Error while %1$s</string>
|
||||||
|
<string name="sync_error_http_dav">Server error</string>
|
||||||
|
<string name="sync_error_local_storage">Database error</string>
|
||||||
<string-array name="sync_error_phases">
|
<string-array name="sync_error_phases">
|
||||||
<item>preparing synchronization</item>
|
<item>preparing synchronization</item>
|
||||||
<item>querying capabilities</item>
|
<item>querying capabilities</item>
|
||||||
@ -203,8 +205,10 @@
|
|||||||
<item>checking sync state</item>
|
<item>checking sync state</item>
|
||||||
<item>listing local entries</item>
|
<item>listing local entries</item>
|
||||||
<item>listing remote entries</item>
|
<item>listing remote entries</item>
|
||||||
|
<item>comparing local/remote entries</item>
|
||||||
<item>downloading remote entries</item>
|
<item>downloading remote entries</item>
|
||||||
<item>saving sync state</item>
|
<item>saving sync state</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string name="sync_error_unauthorized">User name/password wrong</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user