Log resource detection results to viewable string

* new StringLogger
* DavResourceFinder: log to StringLogger; if no collections are found, logs can be views
* DebugInfoActivity: show passed logs
* script to fetch translations from Transifex
* increase version to 0.9-beta2
pull/2/head
Ricki Hirner 9 years ago
parent 58f05986c9
commit 4b5cb30762
No known key found for this signature in database
GPG Key ID: C4A212CF0B2B4566

@ -17,8 +17,8 @@ android {
minSdkVersion 14
targetSdkVersion 23
versionCode 76
versionName "0.9-beta1"
versionCode 77
versionName "0.9-beta2"
buildConfigField "java.util.Date", "buildTime", "new java.util.Date()"
}

@ -8,9 +8,14 @@
package at.bitfire.davdroid.log;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.Marker;
import java.io.PrintWriter;
import lombok.Getter;
/**
* A DAVdroid logger base class that wraps all calls around some standard log() calls.
* @throws UnsupportedOperationException for all methods with Marker
@ -25,13 +30,39 @@ public abstract class CustomLogger implements Logger {
PREFIX_DEBUG = "[debug] ",
PREFIX_TRACE = "[trace] ";
@Getter
protected String name;
protected PrintWriter writer;
protected boolean verbose;
protected abstract void log(String prefix, String msg);
protected abstract void log(String prefix, String format, Object arg);
protected abstract void log(String prefix, String format, Object arg1, Object arg2);
protected abstract void log(String prefix, String format, Object... args);
protected abstract void log(String prefix, String msg, Throwable t);
// CUSTOM LOGGING METHODS
protected void log(String prefix, String msg) {
writer.write(prefix + msg + "\n");
}
protected void log(String prefix, String format, Object arg) {
writer.write(prefix + format.replace("{}", arg.toString()) + "\n");
}
protected void log(String prefix, String format, Object arg1, Object arg2) {
writer.write(prefix + format.replaceFirst("\\{\\}", arg1.toString()).replaceFirst("\\{\\}", arg2.toString()) + "\n");
}
protected void log(String prefix, String format, Object... args) {
String message = prefix;
for (Object arg : args)
format.replaceFirst("\\{\\}", arg.toString());
writer.write(prefix + format + "\n");
}
protected void log(String prefix, String msg, Throwable t) {
writer.write(prefix + msg + " - EXCEPTION:\n");
t.printStackTrace(writer);
ExceptionUtils.printRootCauseStackTrace(t, writer);
}
// STANDARD CALLS

@ -10,21 +10,13 @@ package at.bitfire.davdroid.log;
import android.content.Context;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import lombok.Getter;
public class ExternalFileLogger extends CustomLogger implements Closeable {
@Getter protected final String name;
protected final PrintWriter writer;
public ExternalFileLogger(Context context, String fileName, boolean verbose) throws IOException {
this.verbose = verbose;
@ -41,35 +33,5 @@ public class ExternalFileLogger extends CustomLogger implements Closeable {
writer.close();
}
@Override
protected void log(String prefix, String msg) {
writer.write(prefix + msg + "\n");
}
@Override
protected void log(String prefix, String format, Object arg) {
writer.write(prefix + format.replace("{}", arg.toString()) + "\n");
}
@Override
protected void log(String prefix, String format, Object arg1, Object arg2) {
writer.write(prefix + format.replaceFirst("\\{\\}", arg1.toString()).replaceFirst("\\{\\}", arg2.toString()) + "\n");
}
@Override
protected void log(String prefix, String format, Object... args) {
String message = prefix;
for (Object arg : args)
format.replaceFirst("\\{\\}", arg.toString());
writer.write(prefix + format + "\n");
}
@Override
protected void log(String prefix, String msg, Throwable t) {
writer.write(prefix + msg + " - EXCEPTION:");
t.printStackTrace(writer);
writer.write("CAUSED BY:\n");
ExceptionUtils.printRootCauseStackTrace(t, writer);
}
}

@ -0,0 +1,35 @@
/*
* Copyright © 2013 2015 Ricki Hirner (bitfire web engineering).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package at.bitfire.davdroid.log;
import java.io.PrintWriter;
import java.io.StringWriter;
import lombok.Getter;
public class StringLogger extends CustomLogger {
@Getter protected final String name;
protected final StringWriter stringWriter = new StringWriter();
public StringLogger(String name, boolean verbose) {
this.name = name;
this.verbose = verbose;
writer = new PrintWriter(stringWriter);
}
public String toString() {
return stringWriter.toString();
}
}

@ -44,7 +44,6 @@ import at.bitfire.dav4android.property.CurrentUserPrivilegeSet;
import at.bitfire.dav4android.property.DisplayName;
import at.bitfire.dav4android.property.ResourceType;
import at.bitfire.dav4android.property.SupportedCalendarComponentSet;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.HttpClient;
import lombok.NonNull;
@ -77,12 +76,16 @@ public class DavResourceFinder {
httpClient = new HttpClient(log, context, serverInfo.getUserName(), serverInfo.getPassword(), serverInfo.authPreemptive);
}
public void findResources() throws URISyntaxException, IOException, HttpException, DavException {
findResources(Service.CARDDAV);
findResources(Service.CALDAV);
public void findResources() {
try {
findResources(Service.CARDDAV);
findResources(Service.CALDAV);
} catch(URISyntaxException e) {
log.warn("Invalid user-given URI", e);
}
}
public void findResources(Service service) throws URISyntaxException, IOException, HttpException, DavException {
public void findResources(Service service) throws URISyntaxException {
URI baseURI = serverInfo.getBaseURI();
String domain = null;
@ -95,7 +98,7 @@ public class DavResourceFinder {
} else if (service == Service.CARDDAV)
addressbooks.clear();
Constants.log.info("*** STARTING COLLECTION DISCOVERY FOR SERVICE " + service.name.toUpperCase() + "***");
log.info("*** STARTING COLLECTION DISCOVERY FOR SERVICE " + service.name.toUpperCase() + "***");
if ("http".equals(baseURI.getScheme()) || "https".equals(baseURI.getScheme())) {
HttpUrl userURL = HttpUrl.get(baseURI);
@ -103,7 +106,7 @@ public class DavResourceFinder {
1. user-given URL is a calendar
2. user-given URL has a calendar-home-set property (i.e. is a principal URL)
*/
Constants.log.info("Check whether user-given URL is a calendar collection and/or contains <calendar-home-set> and/or has <current-user-principal>");
log.info("Check whether user-given URL is a calendar collection and/or contains <calendar-home-set> and/or has <current-user-principal>");
DavResource davBase = new DavResource(log, httpClient, userURL);
try {
if (service == Service.CALDAV) {
@ -122,13 +125,13 @@ public class DavResourceFinder {
addIfAddressBook(davBase);
}
} catch (IOException|HttpException|DavException e) {
Constants.log.debug("PROPFIND on user-given URL failed", e);
log.debug("PROPFIND on user-given URL failed", e);
}
if (service == Service.CALDAV) {
CalendarHomeSet calendarHomeSet = (CalendarHomeSet)davBase.properties.get(CalendarHomeSet.NAME);
if (calendarHomeSet != null) {
Constants.log.info("Found <calendar-home-set> at user-given URL");
log.info("Found <calendar-home-set> at user-given URL");
for (String href : calendarHomeSet.hrefs) {
HttpUrl url = userURL.resolve(href);
if (url != null)
@ -138,7 +141,7 @@ public class DavResourceFinder {
} else if (service == Service.CARDDAV) {
AddressbookHomeSet addressbookHomeSet = (AddressbookHomeSet) davBase.properties.get(AddressbookHomeSet.NAME);
if (addressbookHomeSet != null) {
Constants.log.info("Found <addressbook-home-set> at user-given URL");
log.info("Found <addressbook-home-set> at user-given URL");
for (String href : addressbookHomeSet.hrefs) {
HttpUrl url = userURL.resolve(href);
if (url != null)
@ -153,7 +156,7 @@ public class DavResourceFinder {
* Keep in mind that the CalDAV principal URL must not be the CardDAV principal URL! */
if (homeSets.isEmpty())
try {
Constants.log.info("No home sets found, looking for <current-user-principal>");
log.info("No home sets found, looking for <current-user-principal>");
davBase.options();
if ((service == Service.CALDAV && davBase.capabilities.contains("calendar-access")) ||
@ -163,15 +166,15 @@ public class DavResourceFinder {
principalUrl = davBase.location.resolve(currentUserPrincipal.href);
}
} catch(IOException|HttpException|DavException e) {
Constants.log.debug("Couldn't find <current-user-principal> at user-given URL", e);
log.debug("Couldn't find <current-user-principal> at user-given URL", e);
}
if (principalUrl == null)
try {
Constants.log.info("User-given URL doesn't contain <current-user-principal>, trying /.well-known/" + service.name);
log.info("User-given URL doesn't contain <current-user-principal>, trying /.well-known/" + service.name);
principalUrl = getCurrentUserPrincipal(userURL.resolve("/.well-known/" + service.name));
} catch(IOException|HttpException e) {
Constants.log.debug("Couldn't determine <current-user-principal> from well-known " + service + " path", e);
} catch(IOException|HttpException|DavException e) {
log.debug("Couldn't determine <current-user-principal> from well-known " + service + " path", e);
}
if (principalUrl == null)
@ -190,13 +193,17 @@ public class DavResourceFinder {
}
if (principalUrl == null && domain != null) {
Constants.log.info("No principal URL yet, trying SRV/TXT records with domain " + domain);
principalUrl = discoverPrincipalUrl(domain, service);
log.info("No principal URL yet, trying SRV/TXT records with domain " + domain);
try {
principalUrl = discoverPrincipalUrl(domain, service);
} catch (IOException|HttpException|DavException e) {
log.info("Couldn't find principal URL using service discovery");
}
}
// principal URL has been found, get addressbook-home-set/calendar-home-set
if (principalUrl != null) {
Constants.log.info("Principal URL=" + principalUrl + ", getting <calendar-home-set>");
log.info("Principal URL=" + principalUrl + ", getting <calendar-home-set>");
try {
DavResource principal = new DavResource(log, httpClient, principalUrl);
@ -204,7 +211,7 @@ public class DavResourceFinder {
principal.propfind(0, CalendarHomeSet.NAME);
CalendarHomeSet calendarHomeSet = (CalendarHomeSet) principal.properties.get(CalendarHomeSet.NAME);
if (calendarHomeSet != null) {
Constants.log.info("Found <calendar-home-set> at principal URL");
log.info("Found <calendar-home-set> at principal URL");
for (String href : calendarHomeSet.hrefs) {
HttpUrl url = principal.location.resolve(href);
if (url != null)
@ -215,7 +222,7 @@ public class DavResourceFinder {
principal.propfind(0, AddressbookHomeSet.NAME);
AddressbookHomeSet addressbookHomeSet = (AddressbookHomeSet) principal.properties.get(AddressbookHomeSet.NAME);
if (addressbookHomeSet != null) {
Constants.log.info("Found <addressbook-home-set> at principal URL");
log.info("Found <addressbook-home-set> at principal URL");
for (String href : addressbookHomeSet.hrefs) {
HttpUrl url = principal.location.resolve(href);
if (url != null)
@ -225,7 +232,7 @@ public class DavResourceFinder {
}
} catch (IOException|HttpException|DavException e) {
Constants.log.debug("PROPFIND on " + principalUrl + " failed", e);
log.debug("PROPFIND on " + principalUrl + " failed", e);
}
}
@ -233,7 +240,7 @@ public class DavResourceFinder {
for (HttpUrl url : homeSets)
if (service == Service.CALDAV)
try {
Constants.log.info("Listing calendar collections in home set " + url);
log.info("Listing calendar collections in home set " + url);
DavResource homeSet = new DavResource(log, httpClient, url);
homeSet.propfind(1, SupportedCalendarComponentSet.NAME, ResourceType.NAME, DisplayName.NAME, CurrentUserPrivilegeSet.NAME,
CalendarColor.NAME, CalendarDescription.NAME, CalendarTimezone.NAME);
@ -245,11 +252,11 @@ public class DavResourceFinder {
for (DavResource member : homeSet.members)
addIfCalendar(member);
} catch (IOException | HttpException | DavException e) {
Constants.log.debug("PROPFIND on " + url + " failed", e);
log.debug("PROPFIND on " + url + " failed", e);
}
else if (service == Service.CARDDAV)
try {
Constants.log.info("Listing address books in home set " + url);
log.info("Listing address books in home set " + url);
DavResource homeSet = new DavResource(log, httpClient, url);
homeSet.propfind(1, ResourceType.NAME, DisplayName.NAME, CurrentUserPrivilegeSet.NAME, AddressbookDescription.NAME);
@ -260,7 +267,7 @@ public class DavResourceFinder {
for (DavResource member : homeSet.members)
addIfAddressBook(member);
} catch (IOException | HttpException | DavException e) {
Constants.log.debug("PROPFIND on " + url + " failed", e);
log.debug("PROPFIND on " + url + " failed", e);
}
// TODO notify user on errors?
@ -280,7 +287,7 @@ public class DavResourceFinder {
ResourceType resourceType = (ResourceType)dav.properties.get(ResourceType.NAME);
if (resourceType != null && resourceType.types.contains(ResourceType.ADDRESSBOOK)) {
dav.location = UrlUtils.withTrailingSlash(dav.location);
Constants.log.info("Found address book at " + dav.location);
log.info("Found address book at " + dav.location);
addressbooks.put(dav.location, resourceInfo(dav, ServerInfo.ResourceInfo.Type.ADDRESS_BOOK));
}
@ -298,7 +305,7 @@ public class DavResourceFinder {
ResourceType resourceType = (ResourceType)dav.properties.get(ResourceType.NAME);
if (resourceType != null && resourceType.types.contains(ResourceType.CALENDAR)) {
dav.location = UrlUtils.withTrailingSlash(dav.location);
Constants.log.info("Found calendar collection at " + dav.location);
log.info("Found calendar collection at " + dav.location);
boolean supportsEvents = true, supportsTasks = true;
SupportedCalendarComponentSet supportedCalendarComponentSet = (SupportedCalendarComponentSet)dav.properties.get(SupportedCalendarComponentSet.NAME);
@ -376,7 +383,7 @@ public class DavResourceFinder {
List<String> paths = new LinkedList<>(); // there may be multiple paths to try
final String query = "_" + service.name + "s._tcp." + domain;
Constants.log.debug("Looking up SRV records for " + query);
log.debug("Looking up SRV records for " + query);
Record[] records = new Lookup(query, Type.SRV).run();
if (records != null && records.length >= 1) {
// choose SRV record to use (query may return multiple SRV records)
@ -385,7 +392,7 @@ public class DavResourceFinder {
scheme = "https";
fqdn = srv.getTarget().toString(true);
port = srv.getPort();
Constants.log.info("Found " + service + " service: fqdn=" + fqdn + ", port=" + port);
log.info("Found " + service + " service: fqdn=" + fqdn + ", port=" + port);
// look for TXT record too (for initial context path)
records = new Lookup(domain, Type.TXT).run();
@ -394,7 +401,7 @@ public class DavResourceFinder {
for (String segment : (String[])txt.getStrings().toArray(new String[0]))
if (segment.startsWith("path=")) {
paths.add(segment.substring(5));
Constants.log.info("Found TXT record; initial context path=" + paths);
log.info("Found TXT record; initial context path=" + paths);
break;
}
}
@ -413,7 +420,7 @@ public class DavResourceFinder {
.encodedPath(path)
.build();
Constants.log.info("Trying to determine principal from initial context path=" + initialContextPath);
log.info("Trying to determine principal from initial context path=" + initialContextPath);
HttpUrl principal = getCurrentUserPrincipal(initialContextPath);
if (principal != null)
return principal;
@ -434,7 +441,7 @@ public class DavResourceFinder {
if (currentUserPrincipal != null && currentUserPrincipal.href != null) {
HttpUrl principal = url.resolve(currentUserPrincipal.href);
if (principal != null) {
Constants.log.info("Found current-user-principal: " + principal);
log.info("Found current-user-principal: " + principal);
return principal;
}
}
@ -446,7 +453,7 @@ public class DavResourceFinder {
private SRVRecord selectSRVRecord(Record[] records) {
if (records.length > 1)
Constants.log.warn("Multiple SRV records not supported yet; using first one");
log.warn("Multiple SRV records not supported yet; using first one");
return (SRVRecord)records[0];
}

@ -25,7 +25,7 @@ public class ServerInfo implements Serializable {
final private String userName, password;
final boolean authPreemptive;
private String errorMessage;
private String logs;
private ResourceInfo
addressBooks[] = new ResourceInfo[0],
@ -40,8 +40,12 @@ public class ServerInfo implements Serializable {
return false;
}
public boolean isEmpty() {
return addressBooks.length == 0 && calendars.length == 0 && taskLists.length == 0;
}
@RequiredArgsConstructor(suppressConstructorProperties=true)
@RequiredArgsConstructor(suppressConstructorProperties=true)
@Data
public static class ResourceInfo implements Serializable {

@ -39,6 +39,7 @@ import at.bitfire.davdroid.R;
public class DebugInfoActivity extends Activity implements LoaderManager.LoaderCallbacks<String> {
public static final String
KEY_EXCEPTION = "exception",
KEY_LOGS = "logs",
KEY_ACCOUNT = "account",
KEY_AUTHORITY = "authority",
KEY_PHASE = "phase";
@ -109,22 +110,24 @@ public class DebugInfoActivity extends Activity implements LoaderManager.LoaderC
@Override
public String loadInBackground() {
Exception exception = null;
String authority = null;
String logs = null,
authority = null;
Account account = null;
Integer phase = null;
int phase = -1;
if (extras != null) {
exception = (Exception)extras.getSerializable(KEY_EXCEPTION);
logs = extras.getString(KEY_LOGS);
account = extras.getParcelable(KEY_ACCOUNT);
authority = extras.getString(KEY_AUTHORITY);
phase = extras.getInt(KEY_PHASE);
phase = extras.getInt(KEY_PHASE, -1);
}
StringBuilder report = new StringBuilder();
// begin with most specific information
if (phase != null)
if (phase != -1)
report.append("SYNCHRONIZATION INFO\nSynchronization phase: " + phase + "\n");
if (account != null)
report.append("Account name: " + account.name + "\n");
@ -146,6 +149,9 @@ public class DebugInfoActivity extends Activity implements LoaderManager.LoaderC
report.append("\n");
}
if (logs != null)
report.append("LOGS:\n" + logs + "\n");
try {
PackageManager pm = getContext().getPackageManager();
String installedFrom = pm.getInstallerPackageName(BuildConfig.APPLICATION_ID);

@ -9,7 +9,6 @@ package at.bitfire.davdroid.ui.setup;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@ -24,7 +23,9 @@ import android.widget.EditText;
import java.net.URI;
import java.net.URISyntaxException;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.ServerInfo;
public class LoginEmailFragment extends Fragment implements TextWatcher {
@ -53,18 +54,22 @@ public class LoginEmailFragment extends Fragment implements TextWatcher {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.next:
FragmentTransaction ft = getFragmentManager().beginTransaction();
Bundle args = new Bundle();
String email = editEmail.getText().toString();
args.putString(QueryServerDialogFragment.EXTRA_BASE_URI, "mailto:" + email);
args.putString(QueryServerDialogFragment.EXTRA_USER_NAME, email);
args.putString(QueryServerDialogFragment.EXTRA_PASSWORD, editPassword.getText().toString());
args.putBoolean(QueryServerDialogFragment.EXTRA_AUTH_PREEMPTIVE, true);
DialogFragment dialog = new QueryServerDialogFragment();
dialog.setArguments(args);
dialog.show(ft, QueryServerDialogFragment.class.getName());
try {
String email = editEmail.getText().toString();
Bundle args = new Bundle();
args.putSerializable(QueryServerDialogFragment.KEY_SERVER_INFO, new ServerInfo(
new URI("mailto:" + email),
email,
editPassword.getText().toString(),
true
));
DialogFragment dialog = new QueryServerDialogFragment();
dialog.setArguments(args);
dialog.show(getFragmentManager(), QueryServerDialogFragment.class.getName());
} catch(URISyntaxException e) {
Constants.log.debug("Invalid email address", e);
}
break;
default:
return false;

@ -30,7 +30,9 @@ import android.widget.TextView;
import java.net.URI;
import java.net.URISyntaxException;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.ServerInfo;
public class LoginURLFragment extends Fragment implements TextWatcher {
@ -88,20 +90,21 @@ public class LoginURLFragment extends Fragment implements TextWatcher {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.next:
FragmentTransaction ft = getFragmentManager().beginTransaction();
Bundle args = new Bundle();
try {
args.putString(QueryServerDialogFragment.EXTRA_BASE_URI, getBaseURI().toString());
} catch (URISyntaxException e) {
}
args.putString(QueryServerDialogFragment.EXTRA_USER_NAME, editUserName.getText().toString());
args.putString(QueryServerDialogFragment.EXTRA_PASSWORD, editPassword.getText().toString());
args.putBoolean(QueryServerDialogFragment.EXTRA_AUTH_PREEMPTIVE, checkboxPreemptive.isChecked());
DialogFragment dialog = new QueryServerDialogFragment();
dialog.setArguments(args);
dialog.show(ft, QueryServerDialogFragment.class.getName());
try {
ServerInfo serverInfo = new ServerInfo(
getBaseURI(),
editUserName.getText().toString(),
editPassword.getText().toString(),
checkboxPreemptive.isChecked()
);
Bundle args = new Bundle();
args.putSerializable(QueryServerDialogFragment.KEY_SERVER_INFO, serverInfo);
DialogFragment dialog = new QueryServerDialogFragment();
dialog.setArguments(args);
dialog.show(getFragmentManager(), null);
} catch(URISyntaxException e) {
Constants.log.debug("Invalid URI", e);
}
break;
default:
return false;

@ -7,87 +7,126 @@
*/
package at.bitfire.davdroid.ui.setup;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.app.ProgressDialog;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.log.StringLogger;
import at.bitfire.davdroid.resource.DavResourceFinder;
import at.bitfire.davdroid.resource.LocalTaskList;
import at.bitfire.davdroid.resource.ServerInfo;
import at.bitfire.davdroid.ui.DebugInfoActivity;
public class QueryServerDialogFragment extends DialogFragment implements LoaderCallbacks<ServerInfo> {
private static final String TAG = "davdroid.QueryServer";
public static final String
EXTRA_BASE_URI = "base_uri",
EXTRA_USER_NAME = "user_name",
EXTRA_PASSWORD = "password",
EXTRA_AUTH_PREEMPTIVE = "auth_preemptive";
public static final String KEY_SERVER_INFO = "server_info";
@Override
public static QueryServerDialogFragment newInstance(ServerInfo serverInfo) {
Bundle args = new Bundle();
args.putSerializable(KEY_SERVER_INFO, serverInfo);
QueryServerDialogFragment fragment = new QueryServerDialogFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
ProgressDialog dialog = new ProgressDialog(getActivity());
dialog.setCancelable(false);
dialog.setTitle(R.string.setup_resource_detection);
dialog.setIndeterminate(true);
dialog.setMessage(getString(R.string.setup_querying_server));
return dialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog);
setCancelable(false);
Loader<ServerInfo> loader = getLoaderManager().initLoader(0, getArguments(), this);
if (savedInstanceState == null) // http://code.google.com/p/android/issues/detail?id=14944
loader.forceLoad();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.setup_query_server, container, false);
}
@Override
public Loader<ServerInfo> onCreateLoader(int id, Bundle args) {
Log.i(TAG, "onCreateLoader");
return new ServerInfoLoader(getActivity(), args);
}
@Override
public void onLoadFinished(Loader<ServerInfo> loader, ServerInfo serverInfo) {
if (serverInfo.getErrorMessage() != null)
Toast.makeText(getActivity(), serverInfo.getErrorMessage(), Toast.LENGTH_LONG).show();
else {
((AddAccountActivity)getActivity()).serverInfo = serverInfo;
Fragment nextFragment;
if (serverInfo.getTaskLists().length > 0 && !LocalTaskList.tasksProviderAvailable(getActivity().getContentResolver()))
nextFragment = new InstallAppsFragment();
else
nextFragment = new SelectCollectionsFragment();
getFragmentManager().beginTransaction()
.replace(R.id.right_pane, nextFragment)
.addToBackStack(null)
.commitAllowingStateLoss();
}
if (serverInfo.isEmpty()) {
// resource detection didn't find anything
getFragmentManager().beginTransaction()
.add(NothingDetectedFragment.newInstance(serverInfo.getLogs()), null)
.commitAllowingStateLoss();
} else {
((AddAccountActivity) getActivity()).serverInfo = serverInfo;
// resource detection brought some results
Fragment nextFragment;
if (serverInfo.getTaskLists().length > 0 && !LocalTaskList.tasksProviderAvailable(getActivity().getContentResolver()))
nextFragment = new InstallAppsFragment();
else
nextFragment = new SelectCollectionsFragment();
getFragmentManager().beginTransaction()
.replace(R.id.right_pane, nextFragment)
.addToBackStack(null)
.commitAllowingStateLoss();
}
getDialog().dismiss();
}
@Override
public void onLoaderReset(Loader<ServerInfo> arg0) {
}
public static class NothingDetectedFragment extends DialogFragment {
private static String KEY_LOGS = "logs";
public static NothingDetectedFragment newInstance(String logs) {
Bundle args = new Bundle();
args.putString(KEY_LOGS, logs);
NothingDetectedFragment fragment = new NothingDetectedFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.setup_resource_detection)
.setIcon(android.R.drawable.ic_dialog_info)
.setMessage(R.string.setup_no_collections_found)
.setNeutralButton(R.string.setup_view_logs, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(getActivity(), DebugInfoActivity.class);
intent.putExtra(DebugInfoActivity.KEY_LOGS, getArguments().getString(KEY_LOGS));
startActivity(intent);
}
})
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// dismiss
}
})
.create();
}
}
static class ServerInfoLoader extends AsyncTaskLoader<ServerInfo> {
private static final String TAG = "davdroid.ServerInfoLoader";
@ -100,36 +139,22 @@ public class QueryServerDialogFragment extends DialogFragment implements LoaderC
this.args = args;
}
@Override
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
public ServerInfo loadInBackground() {
ServerInfo serverInfo = new ServerInfo(
URI.create(args.getString(EXTRA_BASE_URI)),
args.getString(EXTRA_USER_NAME),
args.getString(EXTRA_PASSWORD),
args.getBoolean(EXTRA_AUTH_PREEMPTIVE)
);
try {
DavResourceFinder finder = new DavResourceFinder(null, context, serverInfo);
finder.findResources();
} catch (URISyntaxException e) {
serverInfo.setErrorMessage(getContext().getString(R.string.exception_uri_syntax, e.getMessage()));
} catch (IOException e) {
// general message
serverInfo.setErrorMessage(getContext().getString(R.string.exception_io, e.getLocalizedMessage()));
// overwrite by more specific message, if possible
/*if (ExceptionUtils.indexOfType(e, CertPathValidatorException.class) != -1)
serverInfo.setErrorMessage(getContext().getString(R.string.exception_cert_path_validation, e.getMessage()));*/
} catch (HttpException e) {
Constants.log.error("HTTP error while querying server info", e);
serverInfo.setErrorMessage(getContext().getString(R.string.exception_http, e.getLocalizedMessage()));
} catch (DavException e) {
Constants.log.error("DAV error while querying server info", e);
serverInfo.setErrorMessage(getContext().getString(R.string.exception_incapable_resource, e.getLocalizedMessage()));
}
ServerInfo serverInfo = (ServerInfo)args.getSerializable(KEY_SERVER_INFO);
StringLogger logger = new StringLogger("DavResourceFinder", true);
DavResourceFinder finder = new DavResourceFinder(logger, context, serverInfo);
finder.findResources();
serverInfo.setLogs(logger.toString());
return serverInfo;
}
}
}

@ -169,8 +169,10 @@
<string name="settings_version_update_title">Settings have been updated</string>
<string name="settings_version_update_description">Internal settings have been updated. If there are problems, please delete your DAVdroid accounts and add them again.</string>
<string name="setup_resource_detection">Resource detection</string>
<string name="setup_no_collections_found">No address books or calendars were found.</string>
<string name="setup_view_logs">View logs</string>
<string name="setup_select_collections">DAVdroid: Select collections</string>
<string name="setup_neither_caldav_nor_carddav">No CalDAV-/CardDAV service is available at this location.</string>
<string name="setup_add_account">Add account</string>
<string name="setup_querying_server">Querying server. Please wait…</string>
<string name="setup_install_apps_info">Plain Android doesn\'t support to-do lists (in contrast to contacts and calendars).</string>

@ -0,0 +1,11 @@
#!/bin/bash
declare -A android
android=([ca]=ca [cs]=cs [de]=de [es]=es [fr]=fr [hu]=hu [nl]=nl [pl]=pl [pt]=pt [ru]=ru [sr]=sr [uk]=uk [zh_CN]=zh-rcn)
for lang in ${!android[@]}
do
target=../app/src/main/res/values-${android[$lang]}
mkdir -p $target
curl -n "https://www.transifex.com/api/2/project/davdroid/resource/davdroid/translation/$lang?file" >$target/strings.xml
done
Loading…
Cancel
Save