1
0
mirror of https://github.com/etesync/android synced 2025-02-10 14:43:17 +00:00
etesync-android/app/src/main/java/com/etesync/syncadapter/AccountUpdateService.java
Tom Hacohen 589f81c50d Add multiple address books support
Android allows only having one address book per account, so until now
users of EteSync were only able to have one address book. This was
always an annoying limitation, but even more so now that journal sharing
is implemented.

Luckily, DAVdroid recently implemented multiple account support by
creating sub-accounts for address books.

This patch is an import of the DAVdroid changes, with adjustments to
work with EteSync, and a few changes that did not make sense for
EteSync. The original commits' split didn't provide any value over this
squash, and the amount of adjustments and addition needed to be done to
apply them, made me decide to squash this change together.

This commit is mostly based on:
dfec72ce6b8ff5e0780e9ac4418c81d080f4b60b
9817594da14ad8dffae18de386e14aeaf41312b9
2017-04-27 11:42:05 +01:00

133 lines
4.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright © 2013 2016 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 com.etesync.syncadapter;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.database.DatabaseUtils;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.NonNull;
import com.etesync.syncadapter.model.ServiceEntity;
import com.etesync.syncadapter.resource.LocalAddressBook;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import at.bitfire.vcard4android.ContactsStorageException;
import io.requery.Persistable;
import io.requery.sql.EntityDataStore;
public class AccountUpdateService extends Service {
public static final String
ACTION_ACCOUNTS_UPDATED = "accountsUpdated";
private final IBinder binder = new InfoBinder();
private final Set<Long> runningRefresh = new HashSet<>();
private final List<WeakReference<RefreshingStatusListener>> refreshingStatusListeners = new LinkedList<>();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
switch (action) {
case ACTION_ACCOUNTS_UPDATED:
cleanupAccounts();
break;
}
}
return START_NOT_STICKY;
}
/* BOUND SERVICE PART
for communicating with the activities
*/
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public interface RefreshingStatusListener {
void onDavRefreshStatusChanged(long id, boolean refreshing);
}
public class InfoBinder extends Binder {
public boolean isRefreshing(long id) {
return runningRefresh.contains(id);
}
public void addRefreshingStatusListener(@NonNull RefreshingStatusListener listener, boolean callImmediate) {
refreshingStatusListeners.add(new WeakReference<>(listener));
if (callImmediate)
for (long id : runningRefresh)
listener.onDavRefreshStatusChanged(id, true);
}
public void removeRefreshingStatusListener(@NonNull RefreshingStatusListener listener) {
for (Iterator<WeakReference<RefreshingStatusListener>> iterator = refreshingStatusListeners.iterator(); iterator.hasNext(); ) {
RefreshingStatusListener item = iterator.next().get();
if (listener.equals(item))
iterator.remove();
}
}
}
/* ACTION RUNNABLES
which actually do the work
*/
@SuppressLint("MissingPermission")
void cleanupAccounts() {
App.log.info("Cleaning up orphaned accounts");
List<String> accountNames = new LinkedList<>();
AccountManager am = AccountManager.get(this);
for (Account account : am.getAccountsByType(App.getAccountType())) {
accountNames.add(account.name);
}
EntityDataStore<Persistable> data = ((App) getApplication()).getData();
// delete orphaned address book accounts
for (Account addrBookAccount : am.getAccountsByType(App.getAddressBookAccountType())) {
LocalAddressBook addressBook = new LocalAddressBook(this, addrBookAccount, null);
try {
if (!accountNames.contains(addressBook.getMainAccount().name))
addressBook.delete();
} catch(ContactsStorageException e) {
App.log.log(Level.SEVERE, "Couldn't get address book main account", e);
}
}
if (accountNames.isEmpty()) {
data.delete(ServiceEntity.class).get().value();
} else {
data.delete(ServiceEntity.class).where(ServiceEntity.ACCOUNT.notIn(accountNames)).get().value();
}
}
}