1
0
mirror of https://github.com/etesync/android synced 2024-12-23 15:18:14 +00:00

New settings management

* Account settings are now read/set using AccountSettings
* AccountSettings upgrades old account settings when necessary
* Settings v1: use absolute URLs instead of paths and discard principal path
  (required for future implementation of well-known URIs)
This commit is contained in:
rfc2822 2014-03-16 17:54:48 +01:00
parent ea94fbee72
commit e0b21abc35
10 changed files with 192 additions and 48 deletions

View File

@ -16,12 +16,5 @@ public class Constants {
ACCOUNT_TYPE = "bitfire.at.davdroid",
ACCOUNT_KEY_USERNAME = "user_name",
ACCOUNT_KEY_BASE_URL = "principal_url",
ACCOUNT_KEY_AUTH_PREEMPTIVE = "auth_preemptive",
ACCOUNT_KEY_ADDRESSBOOK_PATH = "addressbook_path",
ACCOUNT_KEY_ADDRESSBOOK_CTAG = "addressbook_ctag",
WEB_URL_HELP = "http://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app";
}

View File

@ -25,7 +25,6 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
@ -50,7 +49,7 @@ import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.syncadapter.AccountSettings;
import ezvcard.parameter.AddressType;
import ezvcard.parameter.EmailType;
import ezvcard.parameter.ImppType;
@ -66,7 +65,7 @@ import ezvcard.property.Telephone;
public class LocalAddressBook extends LocalCollection<Contact> {
private final static String TAG = "davdroid.LocalAddressBook";
protected AccountManager accountManager;
protected AccountSettings accountSettings;
/* database fields */
@ -91,9 +90,9 @@ public class LocalAddressBook extends LocalCollection<Contact> {
public LocalAddressBook(Account account, ContentProviderClient providerClient, AccountManager accountManager) {
public LocalAddressBook(Account account, ContentProviderClient providerClient, AccountSettings accountSettings) {
super(account, providerClient);
this.accountManager = accountManager;
this.accountSettings = accountSettings;
}
@ -106,12 +105,12 @@ public class LocalAddressBook extends LocalCollection<Contact> {
@Override
public String getCTag() {
return accountManager.getUserData(account, Constants.ACCOUNT_KEY_ADDRESSBOOK_CTAG);
return accountSettings.getAddressBookCTag();
}
@Override
public void setCTag(String cTag) {
accountManager.setUserData(account, Constants.ACCOUNT_KEY_ADDRESSBOOK_CTAG, cTag);
accountSettings.setAddressBookCTag(cTag);
}

View File

@ -69,7 +69,7 @@ public class LocalCalendar extends LocalCollection<Event> {
private static final String TAG = "davdroid.LocalCalendar";
@Getter protected long id;
@Getter protected String path, cTag;
@Getter protected String url, cTag;
protected static String COLLECTION_COLUMN_CTAG = Calendars.CAL_SYNC1;
@ -119,7 +119,7 @@ public class LocalCalendar extends LocalCollection<Event> {
ContentValues values = new ContentValues();
values.put(Calendars.ACCOUNT_NAME, account.name);
values.put(Calendars.ACCOUNT_TYPE, account.type);
values.put(Calendars.NAME, info.getPath());
values.put(Calendars.NAME, info.getURL());
values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle());
values.put(Calendars.CALENDAR_COLOR, color);
values.put(Calendars.OWNER_ACCOUNT, account.name);
@ -158,10 +158,10 @@ public class LocalCalendar extends LocalCollection<Event> {
return calendars.toArray(new LocalCalendar[0]);
}
public LocalCalendar(Account account, ContentProviderClient providerClient, int id, String path, String cTag) throws RemoteException {
public LocalCalendar(Account account, ContentProviderClient providerClient, int id, String url, String cTag) throws RemoteException {
super(account, providerClient);
this.id = id;
this.path = path;
this.url = url;
this.cTag = cTag;
}

View File

@ -86,15 +86,11 @@ public class AccountDetailsFragment extends Fragment implements TextWatcher {
AccountManager accountManager = AccountManager.get(getActivity());
Account account = new Account(accountName, Constants.ACCOUNT_TYPE);
Bundle userData = new Bundle();
userData.putString(Constants.ACCOUNT_KEY_BASE_URL, serverInfo.getBaseURL());
userData.putString(Constants.ACCOUNT_KEY_USERNAME, serverInfo.getUserName());
userData.putString(Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE, Boolean.toString(serverInfo.isAuthPreemptive()));
Bundle userData = AccountSettings.createBundle(serverInfo);
boolean syncContacts = false;
for (ServerInfo.ResourceInfo addressBook : serverInfo.getAddressBooks())
if (addressBook.isEnabled()) {
userData.putString(Constants.ACCOUNT_KEY_ADDRESSBOOK_PATH, addressBook.getPath());
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
syncContacts = true;
continue;

View File

@ -0,0 +1,162 @@
package at.bitfire.davdroid.syncadapter;
import java.net.URI;
import java.net.URISyntaxException;
import lombok.Cleanup;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Calendars;
import android.util.Log;
public class AccountSettings {
private final static String TAG = "davdroid.AccountSettings";
private final static int CURRENT_VERSION = 1;
private final static String
KEY_SETTINGS_VERSION = "version",
KEY_USERNAME = "user_name",
KEY_AUTH_PREEMPTIVE = "auth_preemptive",
KEY_ADDRESSBOOK_URL = "addressbook_url",
KEY_ADDRESSBOOK_CTAG = "addressbook_ctag";
Context context;
AccountManager accountManager;
Account account;
public AccountSettings(Context context, Account account) {
this.context = context;
this.account = account;
accountManager = AccountManager.get(context);
synchronized(AccountSettings.class) {
int version = 0;
try {
version = Integer.parseInt(accountManager.getUserData(account, KEY_SETTINGS_VERSION));
} catch(NumberFormatException e) {
}
if (version < CURRENT_VERSION)
update(version);
}
}
public static Bundle createBundle(ServerInfo serverInfo) {
Bundle bundle = new Bundle();
bundle.putString(KEY_SETTINGS_VERSION, String.valueOf(CURRENT_VERSION));
bundle.putString(KEY_USERNAME, serverInfo.getUserName());
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());
continue;
}
return bundle;
}
// general settings
public String getUserName() {
return accountManager.getUserData(account, KEY_USERNAME);
}
public String getPassword() {
return accountManager.getPassword(account);
}
public boolean getPreemptiveAuth() {
return Boolean.parseBoolean(accountManager.getUserData(account, KEY_AUTH_PREEMPTIVE));
}
// 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);
}
// update from previous account settings
private void update(int fromVersion) {
Log.i(TAG, "Account settings must be updated from v" + fromVersion + " to v" + CURRENT_VERSION);
for (int toVersion = CURRENT_VERSION; toVersion > fromVersion; toVersion--)
update(fromVersion, toVersion);
}
private void update(int fromVersion, int toVersion) {
Log.i(TAG, "Updating account settings from v" + fromVersion + " to " + toVersion);
try {
if (fromVersion == 0 && toVersion == 1)
update_0_1();
else
Log.wtf(TAG, "Don't know how to update settings from v" + fromVersion + " to v" + toVersion);
} catch(Exception e) {
Log.e(TAG, "Couldn't update account settings (DAVdroid will probably crash)!", e);
}
}
private void update_0_1() throws URISyntaxException {
String v0_principalURL = accountManager.getUserData(account, "principal_url"),
v0_addressBookPath = accountManager.getUserData(account, "addressbook_path");
Log.d(TAG, "Old principal URL = " + v0_principalURL);
Log.d(TAG, "Old address book path = " + v0_addressBookPath);
URI principalURI = new URI(v0_principalURL);
// update address book
String addressBookURL = principalURI.resolve(v0_addressBookPath).toASCIIString();
Log.d(TAG, "New address book URL = " + addressBookURL);
accountManager.setUserData(account, "addressbook_url", addressBookURL);
// update calendars
ContentResolver resolver = context.getContentResolver();
Uri calendars = Calendars.CONTENT_URI.buildUpon()
.appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
.appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true").build();
@Cleanup Cursor cursor = resolver.query(calendars, new String[] { Calendars._ID, Calendars.NAME }, null, null, null);
while (cursor != null && cursor.moveToNext()) {
int id = cursor.getInt(0);
String v0_path = cursor.getString(1),
v1_url = principalURI.resolve(v0_path).toASCIIString();
Log.d(TAG, "Updating calendar #" + id + " name: " + v0_path + " -> " + v1_url);
Uri calendar = ContentUris.appendId(Calendars.CONTENT_URI.buildUpon()
.appendQueryParameter(Calendars.ACCOUNT_NAME, account.name)
.appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type)
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true"), id).build();
ContentValues newValues = new ContentValues(1);
newValues.put(Calendars.NAME, v1_url);
if (resolver.update(calendar, newValues, null, null) != 1)
Log.e(TAG, "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, "addressbook_path", null);
Log.d(TAG, "Updated settings successfully!");
accountManager.setUserData(account, KEY_SETTINGS_VERSION, "1");
}
}

View File

@ -10,7 +10,6 @@
******************************************************************************/
package at.bitfire.davdroid.syncadapter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
@ -24,7 +23,6 @@ import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.resource.CalDavCalendar;
import at.bitfire.davdroid.resource.LocalCalendar;
import at.bitfire.davdroid.resource.LocalCollection;
@ -53,17 +51,16 @@ public class CalendarsSyncAdapterService extends Service {
@Override
protected Map<LocalCollection<?>, RemoteCollection<?>> getSyncPairs(Account account, ContentProviderClient provider) {
AccountSettings settings = new AccountSettings(context, account);
String userName = settings.getUserName(),
password = settings.getPassword();
boolean preemptive = settings.getPreemptiveAuth();
try {
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<LocalCollection<?>, RemoteCollection<?>>();
for (LocalCalendar calendar : LocalCalendar.findAll(account, provider)) {
URI baseURI = new URI(accountManager.getUserData(account, Constants.ACCOUNT_KEY_BASE_URL));
URI uri = baseURI.resolve(calendar.getPath());
RemoteCollection<?> dav = new CalDavCalendar(uri.toString(),
accountManager.getUserData(account, Constants.ACCOUNT_KEY_USERNAME),
accountManager.getPassword(account),
Boolean.parseBoolean(accountManager.getUserData(account, Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE)));
RemoteCollection<?> dav = new CalDavCalendar(calendar.getUrl(), userName, password, preemptive);
map.put(calendar, dav);
}
return map;

View File

@ -10,7 +10,6 @@
******************************************************************************/
package at.bitfire.davdroid.syncadapter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
@ -23,7 +22,6 @@ import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.resource.CardDavAddressBook;
import at.bitfire.davdroid.resource.LocalAddressBook;
import at.bitfire.davdroid.resource.LocalCollection;
@ -52,19 +50,18 @@ public class ContactsSyncAdapterService extends Service {
@Override
protected Map<LocalCollection<?>, RemoteCollection<?>> getSyncPairs(Account account, ContentProviderClient provider) {
String addressBookPath = accountManager.getUserData(account, Constants.ACCOUNT_KEY_ADDRESSBOOK_PATH);
if (addressBookPath == null)
AccountSettings settings = new AccountSettings(context, account);
String userName = settings.getUserName(),
password = settings.getPassword();
boolean preemptive = settings.getPreemptiveAuth();
String addressBookURL = settings.getAddressBookURL();
if (addressBookURL == null)
return null;
try {
LocalCollection<?> database = new LocalAddressBook(account, provider, accountManager);
URI uri = new URI(accountManager.getUserData(account, Constants.ACCOUNT_KEY_BASE_URL)).resolve(addressBookPath);
RemoteCollection<?> dav = new CardDavAddressBook(
uri.toString(),
accountManager.getUserData(account, Constants.ACCOUNT_KEY_USERNAME),
accountManager.getPassword(account),
Boolean.parseBoolean(accountManager.getUserData(account, Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE)));
LocalCollection<?> database = new LocalAddressBook(account, provider, settings);
RemoteCollection<?> dav = new CardDavAddressBook(addressBookURL, userName, password, preemptive);
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<LocalCollection<?>, RemoteCollection<?>>();
map.put(database, dav);

View File

@ -167,7 +167,7 @@ public class QueryServerDialogFragment extends DialogFragment implements LoaderC
ServerInfo.ResourceInfo info = new ServerInfo.ResourceInfo(
ServerInfo.ResourceInfo.Type.ADDRESS_BOOK,
resource.isReadOnly(),
resource.getLocation().getRawPath(),
resource.getLocation().toASCIIString(),
resource.getDisplayName(),
resource.getDescription(), resource.getColor()
);
@ -199,7 +199,7 @@ public class QueryServerDialogFragment extends DialogFragment implements LoaderC
ServerInfo.ResourceInfo info = new ServerInfo.ResourceInfo(
ServerInfo.ResourceInfo.Type.CALENDAR,
resource.isReadOnly(),
resource.getLocation().getRawPath(),
resource.getLocation().toASCIIString(),
resource.getDisplayName(),
resource.getDescription(), resource.getColor()
);

View File

@ -134,7 +134,7 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter
String description = info.getDescription();
if (description == null)
description = info.getPath();
description = info.getURL();
// FIXME escape HTML
view.setText(Html.fromHtml(title + "<br/>" + description));

View File

@ -55,7 +55,7 @@ public class ServerInfo implements Serializable {
final Type type;
final boolean readOnly;
final String path, title, description, color;
final String URL, title, description, color;
String timezone;
}