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:
parent
ea94fbee72
commit
e0b21abc35
@ -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";
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
162
src/at/bitfire/davdroid/syncadapter/AccountSettings.java
Normal file
162
src/at/bitfire/davdroid/syncadapter/AccountSettings.java
Normal 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");
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
);
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user