mirror of
https://github.com/etesync/android
synced 2024-11-29 11:28:19 +00:00
Improve error/account settings notifications
* move address book settings from account user data to ContactsContract.SyncState * remove "VCard4 capable?" setting (as it's detected at every sync) * show user notification when updating settings version or when Android version was increased * improve stack trace in DebugInfoActivity * get rid of Guava (use Commons again)
This commit is contained in:
parent
20bc5af4a3
commit
e34abf291e
@ -17,8 +17,8 @@ android {
|
|||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
|
|
||||||
versionCode 75
|
versionCode 76
|
||||||
versionName "0.9-alpha3"
|
versionName "0.9-alpha4"
|
||||||
|
|
||||||
buildConfigField "java.util.Date", "buildTime", "new java.util.Date()"
|
buildConfigField "java.util.Date", "buildTime", "new java.util.Date()"
|
||||||
}
|
}
|
||||||
@ -49,8 +49,8 @@ configurations.all {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.google.guava:guava:18.0'
|
|
||||||
compile 'dnsjava:dnsjava:2.1.7'
|
compile 'dnsjava:dnsjava:2.1.7'
|
||||||
|
compile 'org.apache.commons:commons-lang3:3.4'
|
||||||
provided 'org.projectlombok:lombok:1.16.6'
|
provided 'org.projectlombok:lombok:1.16.6'
|
||||||
compile('org.slf4j:slf4j-android:1.7.12')
|
compile('org.slf4j:slf4j-android:1.7.12')
|
||||||
|
|
||||||
|
@ -14,8 +14,16 @@ public class Constants {
|
|||||||
public static final String
|
public static final String
|
||||||
ACCOUNT_TYPE = "bitfire.at.davdroid",
|
ACCOUNT_TYPE = "bitfire.at.davdroid",
|
||||||
WEB_URL_MAIN = "https://davdroid.bitfire.at/?pk_campaign=davdroid-app",
|
WEB_URL_MAIN = "https://davdroid.bitfire.at/?pk_campaign=davdroid-app",
|
||||||
WEB_URL_HELP = "https://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app",
|
WEB_URL_HELP = "https://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app";
|
||||||
WEB_URL_VIEW_LOGS = "https://github.com/bitfireAT/davdroid/wiki/How-to-view-the-logs";
|
|
||||||
|
|
||||||
public static final Logger log = LoggerFactory.getLogger("davdroid");
|
public static final Logger log = LoggerFactory.getLogger("davdroid");
|
||||||
|
|
||||||
|
// notification IDs
|
||||||
|
public final static int
|
||||||
|
NOTIFICATION_ANDROID_VERSION_UPDATED = 0,
|
||||||
|
NOTIFICATION_ACCOUNT_SETTINGS_UPDATED = 1,
|
||||||
|
NOTIFICATION_CONTACTS_SYNC = 10,
|
||||||
|
NOTIFICATION_CALENDAR_SYNC = 11,
|
||||||
|
NOTIFICATION_TASK_SYNC = 12;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,9 @@ import lombok.Synchronized;
|
|||||||
|
|
||||||
public class LocalAddressBook extends AndroidAddressBook implements LocalCollection {
|
public class LocalAddressBook extends AndroidAddressBook implements LocalCollection {
|
||||||
|
|
||||||
protected static final String SYNC_STATE_CTAG = "ctag";
|
protected static final String
|
||||||
|
SYNC_STATE_CTAG = "ctag",
|
||||||
|
SYNC_STATE_URL = "url";
|
||||||
|
|
||||||
private Bundle syncState = new Bundle();
|
private Bundle syncState = new Bundle();
|
||||||
|
|
||||||
@ -80,6 +82,27 @@ public class LocalAddressBook extends AndroidAddressBook implements LocalCollect
|
|||||||
syncState.clear();
|
syncState.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void writeSyncState() throws ContactsStorageException {
|
||||||
|
@Cleanup("recycle") Parcel parcel = Parcel.obtain();
|
||||||
|
parcel.writeBundle(syncState);
|
||||||
|
setSyncState(parcel.marshall());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getURL() throws ContactsStorageException {
|
||||||
|
synchronized (syncState) {
|
||||||
|
readSyncState();
|
||||||
|
return syncState.getString(SYNC_STATE_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setURL(String url) throws ContactsStorageException {
|
||||||
|
synchronized (syncState) {
|
||||||
|
readSyncState();
|
||||||
|
syncState.putString(SYNC_STATE_URL, url);
|
||||||
|
writeSyncState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCTag() throws ContactsStorageException {
|
public String getCTag() throws ContactsStorageException {
|
||||||
synchronized (syncState) {
|
synchronized (syncState) {
|
||||||
@ -93,11 +116,7 @@ public class LocalAddressBook extends AndroidAddressBook implements LocalCollect
|
|||||||
synchronized (syncState) {
|
synchronized (syncState) {
|
||||||
readSyncState();
|
readSyncState();
|
||||||
syncState.putString(SYNC_STATE_CTAG, cTag);
|
syncState.putString(SYNC_STATE_CTAG, cTag);
|
||||||
|
writeSyncState();
|
||||||
// write sync state bundle
|
|
||||||
@Cleanup("recycle") Parcel parcel = Parcel.obtain();
|
|
||||||
parcel.writeBundle(syncState);
|
|
||||||
setSyncState(parcel.marshall());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +24,10 @@ import android.provider.CalendarContract.Events;
|
|||||||
import android.provider.CalendarContract.Reminders;
|
import android.provider.CalendarContract.Reminders;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
|
|
||||||
import net.fortuna.ical4j.data.CalendarBuilder;
|
|
||||||
import net.fortuna.ical4j.model.component.VTimeZone;
|
import net.fortuna.ical4j.model.component.VTimeZone;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -96,8 +95,8 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
|
|||||||
}
|
}
|
||||||
values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);
|
values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);
|
||||||
if (Build.VERSION.SDK_INT >= 15) {
|
if (Build.VERSION.SDK_INT >= 15) {
|
||||||
values.put(Calendars.ALLOWED_AVAILABILITY, Joiner.on(",").join(Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY));
|
values.put(Calendars.ALLOWED_AVAILABILITY, StringUtils.join(new int[] { Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY }, ","));
|
||||||
values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Joiner.on(",").join(CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE));
|
values.put(Calendars.ALLOWED_ATTENDEE_TYPES, StringUtils.join(new int[] { CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE }, ", "));
|
||||||
}
|
}
|
||||||
return create(account, provider, values);
|
return create(account, provider, values);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ package at.bitfire.davdroid.syncadapter;
|
|||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.content.ContentProviderClient;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
@ -16,32 +19,34 @@ import android.content.Context;
|
|||||||
import android.content.PeriodicSync;
|
import android.content.PeriodicSync;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.provider.CalendarContract.Calendars;
|
import android.provider.CalendarContract.Calendars;
|
||||||
import android.util.Log;
|
import android.provider.ContactsContract;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import at.bitfire.davdroid.Constants;
|
||||||
|
import at.bitfire.davdroid.R;
|
||||||
|
import at.bitfire.davdroid.resource.LocalAddressBook;
|
||||||
import at.bitfire.davdroid.resource.ServerInfo;
|
import at.bitfire.davdroid.resource.ServerInfo;
|
||||||
import ezvcard.VCardVersion;
|
import at.bitfire.vcard4android.ContactsStorageException;
|
||||||
import lombok.Cleanup;
|
import lombok.Cleanup;
|
||||||
|
|
||||||
public class AccountSettings {
|
public class AccountSettings {
|
||||||
private final static String TAG = "davdroid.AccountSettings";
|
private final static int CURRENT_VERSION = 2;
|
||||||
|
|
||||||
private final static int CURRENT_VERSION = 1;
|
|
||||||
private final static String
|
private final static String
|
||||||
KEY_SETTINGS_VERSION = "version",
|
KEY_SETTINGS_VERSION = "version",
|
||||||
|
|
||||||
KEY_USERNAME = "user_name",
|
KEY_USERNAME = "user_name",
|
||||||
KEY_AUTH_PREEMPTIVE = "auth_preemptive",
|
KEY_AUTH_PREEMPTIVE = "auth_preemptive",
|
||||||
|
KEY_LAST_ANDROID_VERSION = "last_android_version";
|
||||||
KEY_ADDRESSBOOK_URL = "addressbook_url",
|
|
||||||
KEY_ADDRESSBOOK_CTAG = "addressbook_ctag",
|
|
||||||
KEY_ADDRESSBOOK_VCARD_VERSION = "addressbook_vcard_version";
|
|
||||||
|
|
||||||
public final static long SYNC_INTERVAL_MANUALLY = -1;
|
public final static long SYNC_INTERVAL_MANUALLY = -1;
|
||||||
|
|
||||||
@ -62,9 +67,42 @@ public class AccountSettings {
|
|||||||
version = Integer.parseInt(accountManager.getUserData(account, KEY_SETTINGS_VERSION));
|
version = Integer.parseInt(accountManager.getUserData(account, KEY_SETTINGS_VERSION));
|
||||||
} catch(NumberFormatException e) {
|
} catch(NumberFormatException e) {
|
||||||
}
|
}
|
||||||
if (version < CURRENT_VERSION)
|
Constants.log.info("AccountSettings version: v" + version + ", should be: " + version);
|
||||||
|
|
||||||
|
if (version < CURRENT_VERSION) {
|
||||||
|
showNotification(Constants.NOTIFICATION_ACCOUNT_SETTINGS_UPDATED,
|
||||||
|
context.getString(R.string.settings_version_update_title),
|
||||||
|
context.getString(R.string.settings_version_update_description));
|
||||||
update(version);
|
update(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check whether Android version has changed
|
||||||
|
int lastAndroidVersion = NumberUtils.toInt(accountManager.getUserData(account, KEY_LAST_ANDROID_VERSION));
|
||||||
|
if (lastAndroidVersion < Build.VERSION.SDK_INT) {
|
||||||
|
// notify user
|
||||||
|
showNotification(Constants.NOTIFICATION_ANDROID_VERSION_UPDATED,
|
||||||
|
context.getString(R.string.settings_android_update_title),
|
||||||
|
context.getString(R.string.settings_android_update_description));
|
||||||
|
|
||||||
|
accountManager.setUserData(account, KEY_LAST_ANDROID_VERSION, String.valueOf(Build.VERSION.SDK_INT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showNotification(int id, String title, String message) {
|
||||||
|
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
Notification.Builder n = new Notification.Builder(context);
|
||||||
|
if (Build.VERSION.SDK_INT >= 16) {
|
||||||
|
n.setPriority(Notification.PRIORITY_HIGH);
|
||||||
|
n.setStyle(new Notification.BigTextStyle().bigText(message));
|
||||||
|
} if (Build.VERSION.SDK_INT >= 20)
|
||||||
|
n.setLocalOnly(true);
|
||||||
|
if (Build.VERSION.SDK_INT >= 21)
|
||||||
|
n.setCategory(Notification.CATEGORY_SYSTEM);
|
||||||
|
n.setSmallIcon(R.drawable.ic_launcher);
|
||||||
|
n.setContentTitle(title);
|
||||||
|
n.setContentText(message);
|
||||||
|
nm.notify(id, Build.VERSION.SDK_INT >= 16 ? n.build() : n.getNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,11 +111,6 @@ public class AccountSettings {
|
|||||||
bundle.putString(KEY_SETTINGS_VERSION, String.valueOf(CURRENT_VERSION));
|
bundle.putString(KEY_SETTINGS_VERSION, String.valueOf(CURRENT_VERSION));
|
||||||
bundle.putString(KEY_USERNAME, serverInfo.getUserName());
|
bundle.putString(KEY_USERNAME, serverInfo.getUserName());
|
||||||
bundle.putString(KEY_AUTH_PREEMPTIVE, Boolean.toString(serverInfo.isAuthPreemptive()));
|
bundle.putString(KEY_AUTH_PREEMPTIVE, Boolean.toString(serverInfo.isAuthPreemptive()));
|
||||||
for (ServerInfo.ResourceInfo addressBook : serverInfo.getAddressBooks())
|
|
||||||
if (addressBook.isEnabled()) {
|
|
||||||
bundle.putString(KEY_ADDRESSBOOK_URL, addressBook.getURL());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,65 +157,44 @@ public class AccountSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// address book (CardDAV) settings
|
|
||||||
|
|
||||||
public String getAddressBookURL() {
|
|
||||||
return accountManager.getUserData(account, KEY_ADDRESSBOOK_URL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAddressBookCTag() {
|
|
||||||
return accountManager.getUserData(account, KEY_ADDRESSBOOK_CTAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddressBookCTag(String cTag) {
|
|
||||||
accountManager.setUserData(account, KEY_ADDRESSBOOK_CTAG, cTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VCardVersion getAddressBookVCardVersion() {
|
|
||||||
VCardVersion version = VCardVersion.V3_0;
|
|
||||||
String versionStr = accountManager.getUserData(account, KEY_ADDRESSBOOK_VCARD_VERSION);
|
|
||||||
if (versionStr != null)
|
|
||||||
version = VCardVersion.valueOfByStr(versionStr);
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddressBookVCardVersion(VCardVersion version) {
|
|
||||||
accountManager.setUserData(account, KEY_ADDRESSBOOK_VCARD_VERSION, version.getVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// update from previous account settings
|
// update from previous account settings
|
||||||
|
|
||||||
private void update(int fromVersion) {
|
private void update(int fromVersion) {
|
||||||
Log.i(TAG, "Account settings must be updated from v" + fromVersion + " to v" + CURRENT_VERSION);
|
for (int toVersion = fromVersion + 1; toVersion <= CURRENT_VERSION; toVersion++)
|
||||||
for (int toVersion = CURRENT_VERSION; toVersion > fromVersion; toVersion--)
|
updateTo(toVersion);
|
||||||
update(fromVersion, toVersion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update(int fromVersion, int toVersion) {
|
private void updateTo(int toVersion) {
|
||||||
Log.i(TAG, "Updating account settings from v" + fromVersion + " to " + toVersion);
|
final int fromVersion = toVersion - 1;
|
||||||
|
Constants.log.info("Updating account settings from v" + fromVersion + " to " + toVersion);
|
||||||
try {
|
try {
|
||||||
if (fromVersion == 0 && toVersion == 1)
|
switch (toVersion) {
|
||||||
|
case 1:
|
||||||
update_0_1();
|
update_0_1();
|
||||||
else
|
break;
|
||||||
Log.wtf(TAG, "Don't know how to update settings from v" + fromVersion + " to v" + toVersion);
|
case 2:
|
||||||
|
update_1_2();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Constants.log.error("Don't know how to update settings from v" + fromVersion + " to v" + toVersion);
|
||||||
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.e(TAG, "Couldn't update account settings (DAVdroid will probably crash)!", e);
|
Constants.log.error("Couldn't update account settings (DAVdroid will probably crash)!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update_0_1() throws URISyntaxException {
|
private void update_0_1() throws URISyntaxException {
|
||||||
String v0_principalURL = accountManager.getUserData(account, "principal_url"),
|
String v0_principalURL = accountManager.getUserData(account, "principal_url"),
|
||||||
v0_addressBookPath = accountManager.getUserData(account, "addressbook_path");
|
v0_addressBookPath = accountManager.getUserData(account, "addressbook_path");
|
||||||
Log.d(TAG, "Old principal URL = " + v0_principalURL);
|
Constants.log.debug("Old principal URL = " + v0_principalURL);
|
||||||
Log.d(TAG, "Old address book path = " + v0_addressBookPath);
|
Constants.log.debug("Old address book path = " + v0_addressBookPath);
|
||||||
|
|
||||||
URI principalURI = new URI(v0_principalURL);
|
URI principalURI = new URI(v0_principalURL);
|
||||||
|
|
||||||
// update address book
|
// update address book
|
||||||
if (v0_addressBookPath != null) {
|
if (v0_addressBookPath != null) {
|
||||||
String addressBookURL = principalURI.resolve(v0_addressBookPath).toASCIIString();
|
String addressBookURL = principalURI.resolve(v0_addressBookPath).toASCIIString();
|
||||||
Log.d(TAG, "New address book URL = " + addressBookURL);
|
Constants.log.debug("New address book URL = " + addressBookURL);
|
||||||
accountManager.setUserData(account, "addressbook_url", addressBookURL);
|
accountManager.setUserData(account, "addressbook_url", addressBookURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +209,7 @@ public class AccountSettings {
|
|||||||
int id = cursor.getInt(0);
|
int id = cursor.getInt(0);
|
||||||
String v0_path = cursor.getString(1),
|
String v0_path = cursor.getString(1),
|
||||||
v1_url = principalURI.resolve(v0_path).toASCIIString();
|
v1_url = principalURI.resolve(v0_path).toASCIIString();
|
||||||
Log.d(TAG, "Updating calendar #" + id + " name: " + v0_path + " -> " + v1_url);
|
Constants.log.debug("Updating calendar #" + id + " name: " + v0_path + " -> " + v1_url);
|
||||||
Uri calendar = ContentUris.appendId(Calendars.CONTENT_URI.buildUpon()
|
Uri calendar = ContentUris.appendId(Calendars.CONTENT_URI.buildUpon()
|
||||||
.appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
|
.appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
|
||||||
.appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
|
.appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
|
||||||
@ -205,14 +217,42 @@ public class AccountSettings {
|
|||||||
ContentValues newValues = new ContentValues(1);
|
ContentValues newValues = new ContentValues(1);
|
||||||
newValues.put(Calendars.NAME, v1_url);
|
newValues.put(Calendars.NAME, v1_url);
|
||||||
if (resolver.update(calendar, newValues, null, null) != 1)
|
if (resolver.update(calendar, newValues, null, null) != 1)
|
||||||
Log.e(TAG, "Number of modified calendars != 1");
|
Constants.log.debug("Number of modified calendars != 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "Cleaning old principal URL and address book path");
|
|
||||||
accountManager.setUserData(account, "principal_url", null);
|
accountManager.setUserData(account, "principal_url", null);
|
||||||
accountManager.setUserData(account, "addressbook_path", null);
|
accountManager.setUserData(account, "addressbook_path", null);
|
||||||
|
|
||||||
Log.d(TAG, "Updated settings successfully!");
|
|
||||||
accountManager.setUserData(account, KEY_SETTINGS_VERSION, "1");
|
accountManager.setUserData(account, KEY_SETTINGS_VERSION, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void update_1_2() throws ContactsStorageException {
|
||||||
|
/* - KEY_ADDRESSBOOK_URL ("addressbook_url"),,
|
||||||
|
- KEY_ADDRESSBOOK_CTAG ("addressbook_ctag"),
|
||||||
|
- KEY_ADDRESSBOOK_VCARD_VERSION ("addressbook_vcard_version") are not used anymore (now stored in ContactsContract.SyncState)
|
||||||
|
- KEY_LAST_ANDROID_VERSION ("last_android_version") has been added
|
||||||
|
*/
|
||||||
|
|
||||||
|
// move previous address book info to ContactsContract.SyncState
|
||||||
|
@Cleanup("release") ContentProviderClient provider = context.getContentResolver().acquireContentProviderClient(ContactsContract.AUTHORITY);
|
||||||
|
if (provider != null) {
|
||||||
|
LocalAddressBook addr = new LocalAddressBook(account, provider);
|
||||||
|
|
||||||
|
String url = accountManager.getUserData(account, "addressbook_url");
|
||||||
|
if (!TextUtils.isEmpty(url))
|
||||||
|
addr.setURL(url);
|
||||||
|
accountManager.setUserData(account, "addressbook_url", null);
|
||||||
|
|
||||||
|
String cTag = accountManager.getUserData(account, "addressbook_ctag");
|
||||||
|
if (!TextUtils.isEmpty(cTag))
|
||||||
|
addr.setCTag(cTag);
|
||||||
|
accountManager.setUserData(account, "addressbook_ctag", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store current Android version
|
||||||
|
accountManager.setUserData(account, KEY_LAST_ANDROID_VERSION, String.valueOf(Build.VERSION.SDK_INT));
|
||||||
|
|
||||||
|
accountManager.setUserData(account, KEY_SETTINGS_VERSION, "2");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,14 @@ import android.os.Bundle;
|
|||||||
import android.provider.CalendarContract.Calendars;
|
import android.provider.CalendarContract.Calendars;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.squareup.okhttp.HttpUrl;
|
import com.squareup.okhttp.HttpUrl;
|
||||||
import com.squareup.okhttp.MediaType;
|
import com.squareup.okhttp.MediaType;
|
||||||
import com.squareup.okhttp.RequestBody;
|
import com.squareup.okhttp.RequestBody;
|
||||||
import com.squareup.okhttp.ResponseBody;
|
import com.squareup.okhttp.ResponseBody;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.Charsets;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -54,13 +55,11 @@ import lombok.Cleanup;
|
|||||||
|
|
||||||
public class CalendarSyncManager extends SyncManager {
|
public class CalendarSyncManager extends SyncManager {
|
||||||
|
|
||||||
protected static final int
|
protected static final int MAX_MULTIGET = 20;
|
||||||
MAX_MULTIGET = 30,
|
|
||||||
NOTIFICATION_ID = 2;
|
|
||||||
|
|
||||||
|
|
||||||
public CalendarSyncManager(Context context, Account account, Bundle extras, SyncResult result, LocalCalendar calendar) {
|
public CalendarSyncManager(Context context, Account account, Bundle extras, SyncResult result, LocalCalendar calendar) {
|
||||||
super(NOTIFICATION_ID, context, account, extras, result);
|
super(Constants.NOTIFICATION_CALENDAR_SYNC, context, account, extras, result);
|
||||||
localCollection = calendar;
|
localCollection = calendar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +125,7 @@ public class CalendarSyncManager extends SyncManager {
|
|||||||
|
|
||||||
// download new/updated iCalendars from server
|
// download new/updated iCalendars from server
|
||||||
for (DavResource[] bunch : ArrayUtils.partition(toDownload.toArray(new DavResource[toDownload.size()]), MAX_MULTIGET)) {
|
for (DavResource[] bunch : ArrayUtils.partition(toDownload.toArray(new DavResource[toDownload.size()]), MAX_MULTIGET)) {
|
||||||
Constants.log.info("Downloading " + Joiner.on(" + ").join(bunch));
|
Constants.log.info("Downloading " + StringUtils.join(bunch, ", "));
|
||||||
|
|
||||||
if (bunch.length == 1) {
|
if (bunch.length == 1) {
|
||||||
// only one contact, use GET
|
// only one contact, use GET
|
||||||
|
@ -13,9 +13,7 @@ import android.content.ContentProviderClient;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SyncResult;
|
import android.content.SyncResult;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.squareup.okhttp.HttpUrl;
|
import com.squareup.okhttp.HttpUrl;
|
||||||
import com.squareup.okhttp.MediaType;
|
import com.squareup.okhttp.MediaType;
|
||||||
import com.squareup.okhttp.Request;
|
import com.squareup.okhttp.Request;
|
||||||
@ -23,6 +21,9 @@ import com.squareup.okhttp.RequestBody;
|
|||||||
import com.squareup.okhttp.Response;
|
import com.squareup.okhttp.Response;
|
||||||
import com.squareup.okhttp.ResponseBody;
|
import com.squareup.okhttp.ResponseBody;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.Charsets;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -30,8 +31,6 @@ import java.nio.charset.Charset;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import at.bitfire.dav4android.DavAddressBook;
|
import at.bitfire.dav4android.DavAddressBook;
|
||||||
import at.bitfire.dav4android.DavResource;
|
import at.bitfire.dav4android.DavResource;
|
||||||
@ -56,27 +55,25 @@ import lombok.Cleanup;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
public class ContactsSyncManager extends SyncManager {
|
public class ContactsSyncManager extends SyncManager {
|
||||||
protected static final int
|
protected static final int MAX_MULTIGET = 10;
|
||||||
MAX_MULTIGET = 10,
|
|
||||||
NOTIFICATION_ID = 1;
|
|
||||||
|
|
||||||
final protected ContentProviderClient provider;
|
final protected ContentProviderClient provider;
|
||||||
protected boolean hasVCard4;
|
protected boolean hasVCard4;
|
||||||
|
|
||||||
|
|
||||||
public ContactsSyncManager(Context context, Account account, Bundle extras, ContentProviderClient provider, SyncResult result) {
|
public ContactsSyncManager(Context context, Account account, Bundle extras, ContentProviderClient provider, SyncResult result) {
|
||||||
super(NOTIFICATION_ID, context, account, extras, result);
|
super(Constants.NOTIFICATION_CONTACTS_SYNC, context, account, extras, result);
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepare() {
|
protected void prepare() throws ContactsStorageException {
|
||||||
collectionURL = HttpUrl.parse(settings.getAddressBookURL());
|
|
||||||
davCollection = new DavAddressBook(httpClient, collectionURL);
|
|
||||||
|
|
||||||
// prepare local address book
|
// prepare local address book
|
||||||
localCollection = new LocalAddressBook(account, provider);
|
localCollection = new LocalAddressBook(account, provider);
|
||||||
|
|
||||||
|
collectionURL = HttpUrl.parse(localAddressBook().getURL());
|
||||||
|
davCollection = new DavAddressBook(httpClient, collectionURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -122,7 +119,7 @@ public class ContactsSyncManager extends SyncManager {
|
|||||||
|
|
||||||
// download new/updated VCards from server
|
// download new/updated VCards from server
|
||||||
for (DavResource[] bunch : ArrayUtils.partition(toDownload.toArray(new DavResource[toDownload.size()]), MAX_MULTIGET)) {
|
for (DavResource[] bunch : ArrayUtils.partition(toDownload.toArray(new DavResource[toDownload.size()]), MAX_MULTIGET)) {
|
||||||
Constants.log.info("Downloading " + TextUtils.join(" + ", bunch));
|
Constants.log.info("Downloading " + StringUtils.join(bunch, ", "));
|
||||||
|
|
||||||
if (bunch.length == 1) {
|
if (bunch.length == 1) {
|
||||||
// only one contact, use GET
|
// only one contact, use GET
|
||||||
|
@ -204,6 +204,9 @@ 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));
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 20)
|
||||||
|
builder.setLocalOnly(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String[] phases = context.getResources().getStringArray(R.array.sync_error_phases);
|
String[] phases = context.getResources().getStringArray(R.array.sync_error_phases);
|
||||||
String message = context.getString(messageString, phases[syncPhase]);
|
String message = context.getString(messageString, phases[syncPhase]);
|
||||||
@ -225,7 +228,7 @@ abstract public class SyncManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
abstract protected void prepare();
|
abstract protected void prepare() throws ContactsStorageException;
|
||||||
|
|
||||||
abstract protected void queryCapabilities() throws IOException, HttpException, DavException, CalendarStorageException, ContactsStorageException;
|
abstract protected void queryCapabilities() throws IOException, HttpException, DavException, CalendarStorageException, ContactsStorageException;
|
||||||
|
|
||||||
|
@ -15,13 +15,13 @@ import android.content.SyncResult;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.squareup.okhttp.HttpUrl;
|
import com.squareup.okhttp.HttpUrl;
|
||||||
import com.squareup.okhttp.MediaType;
|
import com.squareup.okhttp.MediaType;
|
||||||
import com.squareup.okhttp.RequestBody;
|
import com.squareup.okhttp.RequestBody;
|
||||||
import com.squareup.okhttp.ResponseBody;
|
import com.squareup.okhttp.ResponseBody;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.Charsets;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dmfs.provider.tasks.TaskContract.TaskLists;
|
import org.dmfs.provider.tasks.TaskContract.TaskLists;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -56,15 +56,13 @@ import lombok.Cleanup;
|
|||||||
|
|
||||||
public class TasksSyncManager extends SyncManager {
|
public class TasksSyncManager extends SyncManager {
|
||||||
|
|
||||||
protected static final int
|
protected static final int MAX_MULTIGET = 30;
|
||||||
MAX_MULTIGET = 30,
|
|
||||||
NOTIFICATION_ID = 3;
|
|
||||||
|
|
||||||
final protected TaskProvider provider;
|
final protected TaskProvider provider;
|
||||||
|
|
||||||
|
|
||||||
public TasksSyncManager(Context context, Account account, Bundle extras, TaskProvider provider, SyncResult result, LocalTaskList taskList) {
|
public TasksSyncManager(Context context, Account account, Bundle extras, TaskProvider provider, SyncResult result, LocalTaskList taskList) {
|
||||||
super(NOTIFICATION_ID, context, account, extras, result);
|
super(Constants.NOTIFICATION_TASK_SYNC, context, account, extras, result);
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
localCollection = taskList;
|
localCollection = taskList;
|
||||||
}
|
}
|
||||||
@ -124,7 +122,7 @@ public class TasksSyncManager extends SyncManager {
|
|||||||
|
|
||||||
// download new/updated iCalendars from server
|
// download new/updated iCalendars from server
|
||||||
for (DavResource[] bunch : ArrayUtils.partition(toDownload.toArray(new DavResource[toDownload.size()]), MAX_MULTIGET)) {
|
for (DavResource[] bunch : ArrayUtils.partition(toDownload.toArray(new DavResource[toDownload.size()]), MAX_MULTIGET)) {
|
||||||
Constants.log.info("Downloading " + Joiner.on(" + ").join(bunch));
|
Constants.log.info("Downloading " + StringUtils.join(bunch, ", "));
|
||||||
|
|
||||||
if (bunch.length == 1) {
|
if (bunch.length == 1) {
|
||||||
// only one contact, use GET
|
// only one contact, use GET
|
||||||
|
@ -23,18 +23,12 @@ 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 org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
import at.bitfire.dav4android.exception.HttpException;
|
import at.bitfire.dav4android.exception.HttpException;
|
||||||
import at.bitfire.davdroid.BuildConfig;
|
import at.bitfire.davdroid.BuildConfig;
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
import lombok.Cleanup;
|
|
||||||
|
|
||||||
public class DebugInfoActivity extends Activity {
|
public class DebugInfoActivity extends Activity {
|
||||||
public static final String
|
public static final String
|
||||||
@ -141,7 +135,8 @@ public class DebugInfoActivity extends Activity {
|
|||||||
|
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
report.append("STACK TRACE\n");
|
report.append("STACK TRACE\n");
|
||||||
report.append(Throwables.getStackTraceAsString(exception));
|
for (String stackTrace : ExceptionUtils.getRootCauseStackTrace(exception))
|
||||||
|
report.append(stackTrace + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return report.toString();
|
return report.toString();
|
||||||
|
@ -141,22 +141,5 @@ public class AccountFragment extends PreferenceFragment {
|
|||||||
prefSyncTasks.setSummary(R.string.settings_sync_summary_not_available);
|
prefSyncTasks.setSummary(R.string.settings_sync_summary_not_available);
|
||||||
}
|
}
|
||||||
|
|
||||||
// category: address book
|
|
||||||
final CheckBoxPreference prefVCard4 = (CheckBoxPreference) findPreference("vcard4_support");
|
|
||||||
if (settings.getAddressBookURL() != null) { // does this account even have an address book?
|
|
||||||
final VCardVersion vCardVersion = settings.getAddressBookVCardVersion();
|
|
||||||
prefVCard4.setChecked(vCardVersion == VCardVersion.V4_0);
|
|
||||||
prefVCard4.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
// don't change the value (it's not really a setting, only a display)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// account doesn't have an adress book, disable contact settings
|
|
||||||
prefVCard4.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,11 @@ public class AccountDetailsFragment extends Fragment implements TextWatcher {
|
|||||||
public void createLocalCollection(Account account, ServerInfo.ResourceInfo resource) throws ContactsStorageException {
|
public void createLocalCollection(Account account, ServerInfo.ResourceInfo resource) throws ContactsStorageException {
|
||||||
@Cleanup("release") ContentProviderClient provider = getActivity().getContentResolver().acquireContentProviderClient(ContactsContract.AUTHORITY);
|
@Cleanup("release") ContentProviderClient provider = getActivity().getContentResolver().acquireContentProviderClient(ContactsContract.AUTHORITY);
|
||||||
LocalAddressBook addressBook = new LocalAddressBook(account, provider);
|
LocalAddressBook addressBook = new LocalAddressBook(account, provider);
|
||||||
|
|
||||||
|
// set URL
|
||||||
|
addressBook.setURL(resource.getURL());
|
||||||
|
|
||||||
|
// set Settings
|
||||||
ContentValues settings = new ContentValues(2);
|
ContentValues settings = new ContentValues(2);
|
||||||
settings.put(ContactsContract.Settings.SHOULD_SYNC, 1);
|
settings.put(ContactsContract.Settings.SHOULD_SYNC, 1);
|
||||||
settings.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1);
|
settings.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1);
|
||||||
|
@ -144,6 +144,11 @@
|
|||||||
<string name="settings_carddav_vcard4_supported">Kontakte werden als VCard 4.0 gesendet</string>
|
<string name="settings_carddav_vcard4_supported">Kontakte werden als VCard 4.0 gesendet</string>
|
||||||
<string name="settings_carddav_vcard4_not_supported">Kontakte werden als VCard 3.0 gesendet</string>
|
<string name="settings_carddav_vcard4_not_supported">Kontakte werden als VCard 3.0 gesendet</string>
|
||||||
|
|
||||||
|
<string name="settings_android_update_title">Neue Android-Version</string>
|
||||||
|
<string name="settings_android_update_description">Die Änderung der Android-Version kann einen Einfluss auf DAVdroid haben. Falls etwas nicht funktioniert, löschen Sie bitte Ihre DAVdroid-Accounts und fügen Sie sie neu hinzu.</string>
|
||||||
|
<string name="settings_version_update_title">Einstellungen aktualisiert</string>
|
||||||
|
<string name="settings_version_update_description">Interne Einstellungen wurden aktualisiert. Falls etwas nicht funktioniert, löschen Sie bitte Ihre DAVdroid-Accounts und fügen Sie sie neu hinzu.</string>
|
||||||
|
|
||||||
<string name="setup_select_collections">DAVdroid: Ordner auswählen</string>
|
<string name="setup_select_collections">DAVdroid: Ordner auswählen</string>
|
||||||
<string name="setup_neither_caldav_nor_carddav">An dieser Adresse konnte kein CalDAV- oder CardDAV-Dienst gefunden werden.</string>
|
<string name="setup_neither_caldav_nor_carddav">An dieser Adresse konnte kein CalDAV- oder CardDAV-Dienst gefunden werden.</string>
|
||||||
<string name="setup_add_account">Konto hinzufügen</string>
|
<string name="setup_add_account">Konto hinzufügen</string>
|
||||||
@ -178,9 +183,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">Fehler beim %1$s</string>
|
<string name="sync_error">Fehler beim %s</string>
|
||||||
<string name="sync_error_http_dav">Serverfehler</string>
|
<string name="sync_error_http_dav">Serverfehler beim %s</string>
|
||||||
<string name="sync_error_local_storage">Datenbank-Fehler</string>
|
<string name="sync_error_local_storage">Datenbank-Fehler beim %s</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>
|
||||||
|
@ -159,6 +159,11 @@
|
|||||||
<string name="settings_carddav_vcard4_supported">Contacts are sent in VCard 4.0 format</string>
|
<string name="settings_carddav_vcard4_supported">Contacts are sent in VCard 4.0 format</string>
|
||||||
<string name="settings_carddav_vcard4_not_supported">Contacts are sent in VCard 3.0 format</string>
|
<string name="settings_carddav_vcard4_not_supported">Contacts are sent in VCard 3.0 format</string>
|
||||||
|
|
||||||
|
<string name="settings_android_update_title">Android version update</string>
|
||||||
|
<string name="settings_android_update_description">Android version updates may have an impact on how DAVdroid works. If there are problems, please delete your DAVdroid accounts and add them again.</string>
|
||||||
|
<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_select_collections">DAVdroid: Select collections</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_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_add_account">Add account</string>
|
||||||
@ -193,9 +198,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">Error while %1$s</string>
|
<string name="sync_error">Error while %s</string>
|
||||||
<string name="sync_error_http_dav">Server error</string>
|
<string name="sync_error_http_dav">Server error while %s</string>
|
||||||
<string name="sync_error_local_storage">Database error</string>
|
<string name="sync_error_local_storage">Database error while %s</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>
|
||||||
|
@ -59,15 +59,10 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<!--
|
||||||
<PreferenceCategory android:title="@string/settings_carddav">
|
<PreferenceCategory android:title="@string/settings_carddav">
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="vcard4_support"
|
|
||||||
android:title="@string/settings_carddav_vcard4_support"
|
|
||||||
android:persistent="false"
|
|
||||||
android:summaryOn="@string/settings_carddav_vcard4_supported"
|
|
||||||
android:summaryOff="@string/settings_carddav_vcard4_not_supported" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
-->
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 6fc7f30b614ecb23b6fa66b6fd848fd6ddc4bafe
|
Subproject commit 429648cfae534dd0476f813c94ab1cae1f140223
|
@ -1 +1 @@
|
|||||||
Subproject commit 624287708eb7f093d2ddf2012e2c2c124cd6e206
|
Subproject commit 662c48c40ad66e9a77f4f4792587dc04ecc4a74e
|
@ -1 +1 @@
|
|||||||
Subproject commit 83ba3128913ba6e57d021ad003bf992100baae43
|
Subproject commit 18b26fe48896b2683b1e04e8df4464f5ceacf8f3
|
Loading…
Reference in New Issue
Block a user