Commit 1f7298f9 authored by Ricki Hirner's avatar Ricki Hirner 🐑

Don't rely on LOGIN_ACCOUNTS_CHANGED_ACTION

parent c823eb6e
Pipeline #14979657 passed with stages
in 6 minutes and 28 seconds
......@@ -55,20 +55,6 @@
<service android:name=".DavService"/>
<service android:name=".settings.Settings"/>
<receiver android:name=".AccountsChangedReceiver">
<intent-filter>
<action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED"/>
</intent-filter>
</receiver>
<receiver android:name=".PackageChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
<activity
android:name=".ui.AccountsActivity"
android:label="@string/app_name"
......
/*
* Copyright © 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
import android.accounts.AccountManager
import android.accounts.OnAccountsUpdateListener
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import java.util.*
class AccountsChangedReceiver: BroadcastReceiver() {
companion object {
private val listeners = LinkedList<OnAccountsUpdateListener>()
@JvmStatic
fun registerListener(listener: OnAccountsUpdateListener, callImmediately: Boolean) {
listeners += listener
if (callImmediately)
listener.onAccountsUpdated(null)
}
@JvmStatic
fun unregisterListener(listener: OnAccountsUpdateListener) {
listeners -= listener
}
}
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION) {
val serviceIntent = Intent(context, DavService::class.java)
serviceIntent.action = DavService.ACTION_ACCOUNTS_UPDATED
context.startService(serviceIntent)
for (listener in listeners)
listener.onAccountsUpdated(null)
}
}
}
......@@ -9,8 +9,6 @@
package at.bitfire.davdroid
import android.accounts.Account
import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.app.Service
import android.content.ContentValues
......@@ -28,11 +26,9 @@ import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.model.CollectionInfo
import at.bitfire.davdroid.model.ServiceDB.*
import at.bitfire.davdroid.model.ServiceDB.Collections
import at.bitfire.davdroid.resource.LocalAddressBook
import at.bitfire.davdroid.settings.Settings
import at.bitfire.davdroid.ui.DebugInfoActivity
import at.bitfire.davdroid.ui.NotificationUtils
import at.bitfire.vcard4android.ContactsStorageException
import okhttp3.HttpUrl
import org.apache.commons.collections4.iterators.IteratorChain
import org.apache.commons.collections4.iterators.SingletonIterator
......@@ -45,7 +41,6 @@ import kotlin.concurrent.thread
class DavService: Service() {
companion object {
@JvmField val ACTION_ACCOUNTS_UPDATED = "accountsUpdated"
@JvmField val ACTION_REFRESH_COLLECTIONS = "refreshCollections"
@JvmField val EXTRA_DAV_SERVICE_ID = "davServiceID"
}
......@@ -59,8 +54,6 @@ class DavService: Service() {
val id = intent.getLongExtra(EXTRA_DAV_SERVICE_ID, -1)
when (intent.action) {
ACTION_ACCOUNTS_UPDATED ->
cleanupAccounts()
ACTION_REFRESH_COLLECTIONS ->
if (runningRefresh.add(id)) {
thread { refreshCollections(id) }
......@@ -110,42 +103,7 @@ class DavService: Service() {
which actually do the work
*/
@SuppressLint("MissingPermission")
fun cleanupAccounts() {
Logger.log.info("Cleaning up orphaned accounts")
OpenHelper(this).use { dbHelper ->
val db = dbHelper.writableDatabase
val sqlAccountNames = LinkedList<String>()
val accountNames = HashSet<String>()
val accountManager = AccountManager.get(this)
for (account in accountManager.getAccountsByType(getString(R.string.account_type))) {
sqlAccountNames.add(DatabaseUtils.sqlEscapeString(account.name))
accountNames += account.name
}
// delete orphaned address book accounts
accountManager.getAccountsByType(getString(R.string.account_type_address_book))
.map { LocalAddressBook(this, it, null) }
.forEach {
try {
if (!accountNames.contains(it.getMainAccount().name))
it.delete()
} catch(e: ContactsStorageException) {
Logger.log.log(Level.SEVERE, "Couldn't get address book main account", e)
}
}
// delete orphaned services in DB
if (sqlAccountNames.isEmpty())
db.delete(Services._TABLE, null, null)
else
db.delete(Services._TABLE, "${Services.ACCOUNT_NAME} NOT IN (${sqlAccountNames.joinToString(",")})", null)
}
}
fun refreshCollections(service: Long) {
private fun refreshCollections(service: Long) {
OpenHelper(this@DavService).use { dbHelper ->
val db = dbHelper.writableDatabase
......
......@@ -7,28 +7,93 @@
*/
package at.bitfire.davdroid.syncadapter
import android.accounts.AbstractAccountAuthenticator
import android.accounts.Account
import android.accounts.AccountAuthenticatorResponse
import android.accounts.AccountManager
import android.accounts.*
import android.app.Service
import android.content.Context
import android.content.Intent
import android.database.DatabaseUtils
import android.os.Bundle
import at.bitfire.davdroid.R
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.model.ServiceDB
import at.bitfire.davdroid.resource.LocalAddressBook
import at.bitfire.davdroid.ui.setup.LoginActivity
import at.bitfire.vcard4android.ContactsStorageException
import java.util.*
import java.util.logging.Level
class AccountAuthenticatorService: Service() {
/**
* Account authenticator for the main DAVdroid account type.
*
* Gets started when a DAVdroid account is removed, too, so it also watches for account removals
* and contains the corresponding cleanup code.
*/
class AccountAuthenticatorService: Service(), OnAccountsUpdateListener {
companion object {
fun cleanupAccounts(context: Context) {
Logger.log.info("Cleaning up orphaned accounts")
ServiceDB.OpenHelper(context).use { dbHelper ->
val db = dbHelper.writableDatabase
val sqlAccountNames = LinkedList<String>()
val accountNames = HashSet<String>()
val accountManager = AccountManager.get(context)
for (account in accountManager.getAccountsByType(context.getString(R.string.account_type))) {
sqlAccountNames.add(DatabaseUtils.sqlEscapeString(account.name))
accountNames += account.name
}
// delete orphaned address book accounts
accountManager.getAccountsByType(context.getString(R.string.account_type_address_book))
.map { LocalAddressBook(context, it, null) }
.forEach {
try {
if (!accountNames.contains(it.getMainAccount().name))
it.delete()
} catch(e: ContactsStorageException) {
Logger.log.log(Level.SEVERE, "Couldn't get address book main account", e)
}
}
// delete orphaned services in DB
if (sqlAccountNames.isEmpty())
db.delete(ServiceDB.Services._TABLE, null, null)
else
db.delete(ServiceDB.Services._TABLE, "${ServiceDB.Services.ACCOUNT_NAME} NOT IN (${sqlAccountNames.joinToString(",")})", null)
}
}
}
private lateinit var accountManager: AccountManager
private lateinit var accountAuthenticator: AccountAuthenticator
override fun onCreate() {
accountManager = AccountManager.get(this)
accountManager.addOnAccountsUpdatedListener(this, null, true)
accountAuthenticator = AccountAuthenticator(this)
}
override fun onDestroy() {
super.onDestroy()
accountManager.removeOnAccountsUpdatedListener(this)
}
override fun onBind(intent: Intent?) =
accountAuthenticator.iBinder.takeIf { intent?.action == android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT }
override fun onAccountsUpdated(accounts: Array<out Account>?) {
cleanupAccounts(this)
}
private class AccountAuthenticator(
val context: Context
): AbstractAccountAuthenticator(context) {
......
......@@ -5,7 +5,6 @@
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package at.bitfire.davdroid.syncadapter
import android.accounts.AbstractAccountAuthenticator
......
......@@ -24,7 +24,6 @@ import android.view.ViewGroup
import android.widget.AbsListView
import android.widget.AdapterView
import android.widget.ArrayAdapter
import at.bitfire.davdroid.AccountsChangedReceiver
import at.bitfire.davdroid.R
import kotlinx.android.synthetic.main.account_list_item.view.*
......@@ -69,11 +68,13 @@ class AccountListFragment: ListFragment(), LoaderManager.LoaderCallbacks<Array<A
context: Context
): AsyncTaskLoader<Array<Account>>(context), OnAccountsUpdateListener {
val accountManager = AccountManager.get(context)!!
override fun onStartLoading() =
AccountsChangedReceiver.registerListener(this, true)
accountManager.addOnAccountsUpdatedListener(this, null, true)
override fun onStopLoading() =
AccountsChangedReceiver.unregisterListener(this)
accountManager.removeOnAccountsUpdatedListener(this)
override fun onAccountsUpdated(accounts: Array<Account>?) =
forceLoad()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment