diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index cdae79e680572c3c89cd2027221c54a2ee5217ea..15b95a47f906c290019e7f7635481c95910d4242 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -261,6 +261,21 @@
android:resource="@xml/contacts"/>
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/at/bitfire/davdroid/MailAccountSyncHelper.kt b/app/src/main/java/at/bitfire/davdroid/MailAccountSyncHelper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..daaa68f9bb10ce130e38c0d9137cefa981b58add
--- /dev/null
+++ b/app/src/main/java/at/bitfire/davdroid/MailAccountSyncHelper.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright ECORP SAS 2022
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package at.bitfire.davdroid
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+
+object MailAccountSyncHelper {
+
+ private const val MAIL_PACKAGE = "foundation.e.mail"
+ private const val MAIL_RECEIVER_CLASS = "com.fsck.k9.account.AccountSyncReceiver"
+ private const val ACTION_PREFIX = "foundation.e.accountmanager.account."
+
+ fun accountLoggedIn(applicationContext : Context?) {
+ val intent = getIntent()
+ intent.action = ACTION_PREFIX + "create"
+ applicationContext?.sendBroadcast(intent)
+ }
+
+ fun accountLoggedOut(applicationContext: Context?, email: String?) {
+ email?.let {
+ if (!it.contains("@")) {
+ return@let
+ }
+ val intent = getIntent()
+ intent.action = ACTION_PREFIX + "remove"
+ intent.putExtra("account", it)
+ applicationContext?.sendBroadcast(intent)
+ }
+ }
+
+ private fun getIntent() : Intent {
+ val intent = Intent()
+ intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+ intent.component = ComponentName(MAIL_PACKAGE, MAIL_RECEIVER_CLASS)
+ return intent
+ }
+}
diff --git a/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt b/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt
index f616d0cea1c96e963353e00a3afe0af3884735b5..d3d04cf6680876b4201f41f7e68449b62d372852 100644
--- a/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt
+++ b/app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt
@@ -87,8 +87,9 @@ class AccountSettings(
/** Stores the tasks sync interval (in seconds) so that it can be set again when the provider is switched */
const val KEY_SYNC_INTERVAL_TASKS = "sync_interval_tasks"
-
const val KEY_USERNAME = "user_name"
+ const val KEY_EMAIL_ADDRESS = "email_address"
+ const val KEY_AUTH_STATE = "auth_state"
const val KEY_CERTIFICATE_ALIAS = "certificate_alias"
const val KEY_WIFI_ONLY = "wifi_only" // sync on WiFi only (default: false)
@@ -141,6 +142,8 @@ class AccountSettings(
if (credentials != null) {
if (credentials.userName != null)
bundle.putString(KEY_USERNAME, credentials.userName)
+ bundle.putString(KEY_EMAIL_ADDRESS, credentials.userName)
+
if (credentials.certificateAlias != null)
bundle.putString(KEY_CERTIFICATE_ALIAS, credentials.certificateAlias)
}
diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/MailSyncAdapterService.kt b/app/src/main/java/at/bitfire/davdroid/syncadapter/MailSyncAdapterService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..afaf4c1372c2bd2156f70ba73ed211f2850ccc4f
--- /dev/null
+++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/MailSyncAdapterService.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright ECORP SAS 2022
+ * 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.syncadapter
+
+import android.accounts.Account
+import android.content.*
+import android.os.Bundle
+import at.bitfire.davdroid.HttpClient
+import at.bitfire.davdroid.db.AppDatabase
+
+class MailSyncAdapterService : SyncAdapterService() {
+
+ override fun syncAdapter() = MailSyncAdapter(this, appDatabase)
+
+ class MailSyncAdapter(
+ context: Context,
+ appDatabase: AppDatabase
+ ): SyncAdapter(context, appDatabase) {
+
+ override fun sync(
+ account: Account,
+ extras: Bundle,
+ authority: String,
+ httpClient: Lazy,
+ provider: ContentProviderClient,
+ syncResult: SyncResult
+ ) {
+ // Unused
+ }
+ }
+
+}
diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/AccountActivity.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/AccountActivity.kt
index fd4d08c953fee6c17c5db0e3dad7ca1659beec76..daed3cd60c1449a2e8bad67992161e6b16003d84 100644
--- a/app/src/main/java/at/bitfire/davdroid/ui/account/AccountActivity.kt
+++ b/app/src/main/java/at/bitfire/davdroid/ui/account/AccountActivity.kt
@@ -21,8 +21,9 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.lifecycle.*
import at.bitfire.davdroid.DavUtils
-import foundation.e.accountmanager.R
-
+import at.bitfire.davdroid.MailAccountSyncHelper
+import at.bitfire.davdroid.R
+import at.bitfire.davdroid.databinding.ActivityAccountBinding
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.Collection
import at.bitfire.davdroid.db.Service
@@ -126,12 +127,13 @@ class AccountActivity: AppCompatActivity() {
private fun deleteAccount() {
val accountManager = AccountManager.get(this)
-
+ val email = accountManager.getUserData(model.account, AccountSettings.KEY_EMAIL_ADDRESS)
if (Build.VERSION.SDK_INT >= 22)
accountManager.removeAccount(model.account, this, { future ->
try {
if (future.result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT))
Handler(Looper.getMainLooper()).post {
+ MailAccountSyncHelper.accountLoggedOut(applicationContext, email)
finish()
}
} catch(e: Exception) {
@@ -142,6 +144,7 @@ class AccountActivity: AppCompatActivity() {
accountManager.removeAccount(model.account, { future ->
try {
if (future.result)
+ MailAccountSyncHelper.accountLoggedOut(applicationContext, email)
Handler(Looper.getMainLooper()).post {
finish()
}
diff --git a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt
index 614ab209ffab66ff815763ed5f860a8e57063e99..193af98b1cecc2b1096777baab9434269bfea5d1 100644
--- a/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt
+++ b/app/src/main/java/at/bitfire/davdroid/ui/setup/AccountDetailsFragment.kt
@@ -5,6 +5,7 @@
package at.bitfire.davdroid.ui.setup
import android.accounts.Account
+import android.accounts.AccountAuthenticatorResponse
import android.accounts.AccountManager
import android.content.ContentResolver
import android.content.Context
@@ -22,8 +23,9 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.*
import at.bitfire.davdroid.DavService
import at.bitfire.davdroid.InvalidAccountException
-import foundation.e.accountmanager.R
-
+import at.bitfire.davdroid.MailAccountSyncHelper
+import at.bitfire.davdroid.R
+import at.bitfire.davdroid.databinding.LoginAccountDetailsBinding
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.Credentials
import at.bitfire.davdroid.db.HomeSet
@@ -106,6 +108,7 @@ class AccountDetailsFragment : Fragment() {
GroupMethod.valueOf(groupMethodName)
).observe(viewLifecycleOwner, Observer { success ->
if (success) {
+ MailAccountSyncHelper.accountLoggedIn(context?.applicationContext)
// close Create account activity
requireActivity().finish()
// open Account activity for created account
@@ -113,9 +116,16 @@ class AccountDetailsFragment : Fragment() {
val account = Account(name, getString(R.string.account_type))
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, account)
startActivity(intent)
+ if (activity!!.intent.hasExtra(AccountManager
+ .KEY_ACCOUNT_AUTHENTICATOR_RESPONSE) && activity!!.intent
+ .getParcelableExtra(AccountManager
+ .KEY_ACCOUNT_AUTHENTICATOR_RESPONSE) != null) {
+ activity!!.intent
+ .getParcelableExtra(AccountManager
+ .KEY_ACCOUNT_AUTHENTICATOR_RESPONSE)?.onResult(null)
+ }
} else {
Snackbar.make(requireActivity().findViewById(android.R.id.content), R.string.login_account_not_created, Snackbar.LENGTH_LONG).show()
-
v.createAccountProgress.visibility = View.GONE
v.createAccount.visibility = View.VISIBLE
}
@@ -155,6 +165,7 @@ class AccountDetailsFragment : Fragment() {
nameError.value = null
}
+
fun createAccount(name: String, credentials: Credentials?, config: DavResourceFinder.Configuration, groupMethod: GroupMethod): LiveData {
val result = MutableLiveData()
viewModelScope.launch(Dispatchers.Default + NonCancellable) {
@@ -168,6 +179,55 @@ class AccountDetailsFragment : Fragment() {
result.postValue(false)
return@launch
}
+ val accountManager = AccountManager.get(context)
+ var accountType = context!!.getString(R.string.account_type)
+ if (!accountManager.addAccountExplicitly(account, credentials!!.password, userData)) {
+ if (accountType == context.getString(R.string.google_account_type)) {
+ for (googleAccount in accountManager.getAccountsByType(
+ context.getString(
+ R.string.google_account_type
+ )
+ )) {
+ if (userData.get(AccountSettings.KEY_EMAIL_ADDRESS) == accountManager
+ .getUserData(account, AccountSettings.KEY_EMAIL_ADDRESS)
+ ) {
+ accountManager.setUserData(
+ googleAccount, AccountSettings.KEY_AUTH_STATE,
+ userData.getString(AccountSettings.KEY_AUTH_STATE)
+ )
+ }
+ }
+ }
+ }
+ if (!credentials.password.isNullOrEmpty()) {
+ accountManager.setPassword(account, credentials.password)
+ }
+
+ ContentResolver.setSyncAutomatically(
+ account,
+ context.getString(R.string.notes_authority),
+ true
+ )
+ ContentResolver.setSyncAutomatically(
+ account,
+ context.getString(R.string.email_authority),
+ true
+ )
+ ContentResolver.setSyncAutomatically(
+ account,
+ context.getString(R.string.media_authority),
+ true
+ )
+ ContentResolver.setSyncAutomatically(
+ account,
+ context.getString(R.string.app_data_authority),
+ true
+ )
+ ContentResolver.setSyncAutomatically(
+ account,
+ context.getString(R.string.metered_edrive_authority),
+ true
+ )
// add entries for account to service DB
Logger.log.log(Level.INFO, "Writing account configuration to database", config)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index eebfb386f865d68bc96a66fb0005e947fc53a8d5..f93b273dc35a14735737c49c6e79adfcbd1b78b2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,6 +11,7 @@
Google
bitfire.at.davdroid.google
+ e.foundation.webdav.eelo
at.bitfire.davdroid.address_book
/e/
diff --git a/app/src/main/res/xml/eelo_sync_email.xml b/app/src/main/res/xml/eelo_sync_email.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1e27619597c9b3569360c22d35d3ab4fad97ba8a
--- /dev/null
+++ b/app/src/main/res/xml/eelo_sync_email.xml
@@ -0,0 +1,15 @@
+
+
+
+