From b36bfd9a2bd340bcc9b4c715014b9e7211ec8c45 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 6 Nov 2024 16:18:55 +0100 Subject: [PATCH 01/31] feature: Add very basic code structure to notifiy a request to user to switch to openID for /e/ account --- app/src/main/AndroidManifest.xml | 6 ++ .../receiver/BootCompletedReceiver.kt | 71 +++++++++++++++++++ .../davdroid/receiver/LogoutReceiver.kt | 11 +++ 3 files changed, 88 insertions(+) create mode 100644 app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 30e04639b..2299dfee3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -703,6 +703,12 @@ + + + + try { + val token = future.result.getString(AccountManager.KEY_AUTHTOKEN) + } catch (e: Exception) { + println("Error retrieving token for account ${account.name}: ${e.message}") } + }, null) + + val isPasswordNull = accountManager.getPassword(account).isNullOrEmpty() + + return isPasswordNull && authToken != null } + private fun notifyOpenIdSwitchRequest(account: Account, + notificationManager: NotificationManager, + context: Context) { + val notifId = 3310 + val notifTitle = "${account.name}: Switch to OpenId" + val notifText = "Now that OpenId is available, you should log out and re-loggin your account." + val notifIntent = generateLogOutIntent(account.name, context) + + val notification = NotificationCompat.Builder(context, "your_channel_id") + .setContentTitle(notifTitle) + .setContentText(notifText) + .setSmallIcon(R.drawable.ic_info) + .setContentIntent(notifIntent) + .setAutoCancel(true) + .build() + + notificationManager.notify(notifId, notification) + } + + private fun generateLogOutIntent(accountName: String, context: Context): PendingIntent { + val logoutIntent = Intent(context, LogoutReceiver::class.java).apply { + putExtra("ACCOUNT_NAME", accountName) + } + + return PendingIntent.getBroadcast(context, + 0, + logoutIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + } } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt new file mode 100644 index 000000000..0b953b20a --- /dev/null +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt @@ -0,0 +1,11 @@ +package at.bitfire.davdroid.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent + +class LogoutReceiver(): BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + TODO("Not yet implemented") + } +} \ No newline at end of file -- GitLab From bc0382ce3fdc5bd71057fd516098dbde390a140f Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 7 Nov 2024 16:24:45 +0100 Subject: [PATCH 02/31] refactor: replace checking AUTH_TOKEN by checking if auth_state is in user data refactor: minor various refactoring like adding notification title & text in strings.xml --- .../receiver/BootCompletedReceiver.kt | 41 ++++++------------- app/src/main/res/values/strings.xml | 3 ++ 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 40bc90967..9e36dbd45 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -6,18 +6,17 @@ package at.bitfire.davdroid.receiver import android.accounts.Account import android.accounts.AccountManager -import android.app.NotificationManager import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.os.Bundle import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat import at.bitfire.davdroid.R import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.AccountUtils -import com.owncloud.android.lib.common.accounts.AccountTypeUtils +import at.bitfire.davdroid.ui.NotificationUtils.notifyIfPossible /** * There are circumstances when Android drops automatic sync of accounts and resets them @@ -30,7 +29,6 @@ class BootCompletedReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Logger.log.info("Device has been rebooted; checking sync intervals etc.") - val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val isOpenIdAvailable = isOpenIdAvailable() val eAccountType = context.getString(R.string.eelo_account_type) @@ -44,41 +42,27 @@ class BootCompletedReceiver: BroadcastReceiver() { accountSettings.initSync() if (it.type.equals(eAccountType) && !isLoggedWithOpenId(it, accountManager)) { - notifyOpenIdSwitchRequest(it, notificationManager, context) + notifySwitchToOpenId(it, context) } } } - /** - * Check if OpenID is implemented in current version of AccountManager - */ private fun isOpenIdAvailable(): Boolean { return false } private fun isLoggedWithOpenId(account: Account, accountManager: AccountManager): Boolean { - val authTokenType = AccountTypeUtils.getAuthTokenTypePass(account.type) - - val authToken = accountManager.getAuthToken(account, authTokenType, Bundle(), false, { future -> - try { - val token = future.result.getString(AccountManager.KEY_AUTHTOKEN) - } catch (e: Exception) { - println("Error retrieving token for account ${account.name}: ${e.message}") - } - }, null) - + val hasAuthStateData = accountManager.getUserData(account, AccountSettings.KEY_AUTH_STATE) != null val isPasswordNull = accountManager.getPassword(account).isNullOrEmpty() - - return isPasswordNull && authToken != null + return isPasswordNull && hasAuthStateData } - private fun notifyOpenIdSwitchRequest(account: Account, - notificationManager: NotificationManager, - context: Context) { + private fun notifySwitchToOpenId(account: Account, context: Context) { + val notifTag = "Switch to openID" val notifId = 3310 - val notifTitle = "${account.name}: Switch to OpenId" - val notifText = "Now that OpenId is available, you should log out and re-loggin your account." - val notifIntent = generateLogOutIntent(account.name, context) + val notifTitle = context.getString(R.string.notification_account_title) + val notifText = context.getString(R.string.notification_switch_to_openId_text) + val notifIntent = generateLogoutIntent(account.name, context) val notification = NotificationCompat.Builder(context, "your_channel_id") .setContentTitle(notifTitle) @@ -88,10 +72,11 @@ class BootCompletedReceiver: BroadcastReceiver() { .setAutoCancel(true) .build() - notificationManager.notify(notifId, notification) + val notificationManager = NotificationManagerCompat.from(context) + notificationManager.notifyIfPossible(notifTag, notifId, notification) } - private fun generateLogOutIntent(accountName: String, context: Context): PendingIntent { + private fun generateLogoutIntent(accountName: String, context: Context): PendingIntent { val logoutIntent = Intent(context, LogoutReceiver::class.java).apply { putExtra("ACCOUNT_NAME", accountName) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 47579443b..e08b3c004 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -43,6 +43,7 @@ Database corrupted All accounts have been removed locally. + Debugging Other important messages Low-priority status messages @@ -53,6 +54,8 @@ Non-fatal synchronization problems like certain invalid files Network and I/O errors Timeouts, connection problems, etc. (often temporary) + Your account %1$s + A new login service for a better experience is available. Tap the notification to start using it. Your data. Your choice. -- GitLab From 1ab43649593404038f69cdd51d2e764a5ab3d3c7 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Fri, 8 Nov 2024 11:54:23 +0100 Subject: [PATCH 03/31] feature: start to implement the LogoutReceiver chore: add small refactoring about the notification --- .../receiver/BootCompletedReceiver.kt | 16 +++++++------- .../davdroid/receiver/LogoutReceiver.kt | 22 ++++++++++++++++++- .../bitfire/davdroid/ui/NotificationUtils.kt | 1 + 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 9e36dbd45..25d0ee1a0 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -16,6 +16,7 @@ import at.bitfire.davdroid.R import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.AccountUtils +import at.bitfire.davdroid.ui.NotificationUtils.NOTIFY_SWITCH_TO_OPENID import at.bitfire.davdroid.ui.NotificationUtils.notifyIfPossible /** @@ -30,7 +31,7 @@ class BootCompletedReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Logger.log.info("Device has been rebooted; checking sync intervals etc.") - val isOpenIdAvailable = isOpenIdAvailable() +// val isOpenIdAvailable = isOpenIdAvailable() val eAccountType = context.getString(R.string.eelo_account_type) val accountManager = AccountManager.get(context) @@ -46,10 +47,10 @@ class BootCompletedReceiver: BroadcastReceiver() { } } } - - private fun isOpenIdAvailable(): Boolean { - return false - } + //TODO will I need it ? +// private fun isOpenIdAvailable(): Boolean { +// return false +// } private fun isLoggedWithOpenId(account: Account, accountManager: AccountManager): Boolean { val hasAuthStateData = accountManager.getUserData(account, AccountSettings.KEY_AUTH_STATE) != null @@ -59,7 +60,6 @@ class BootCompletedReceiver: BroadcastReceiver() { private fun notifySwitchToOpenId(account: Account, context: Context) { val notifTag = "Switch to openID" - val notifId = 3310 val notifTitle = context.getString(R.string.notification_account_title) val notifText = context.getString(R.string.notification_switch_to_openId_text) val notifIntent = generateLogoutIntent(account.name, context) @@ -73,12 +73,12 @@ class BootCompletedReceiver: BroadcastReceiver() { .build() val notificationManager = NotificationManagerCompat.from(context) - notificationManager.notifyIfPossible(notifTag, notifId, notification) + notificationManager.notifyIfPossible(notifTag, NOTIFY_SWITCH_TO_OPENID, notification) } private fun generateLogoutIntent(accountName: String, context: Context): PendingIntent { val logoutIntent = Intent(context, LogoutReceiver::class.java).apply { - putExtra("ACCOUNT_NAME", accountName) + putExtra(AccountManager.KEY_ACCOUNT_NAME, accountName) } return PendingIntent.getBroadcast(context, diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt index 0b953b20a..f58d6207e 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt @@ -1,11 +1,31 @@ package at.bitfire.davdroid.receiver +import android.accounts.Account +import android.accounts.AccountManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import at.bitfire.davdroid.R +import at.bitfire.davdroid.log.Logger class LogoutReceiver(): BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { - TODO("Not yet implemented") + Logger.log.info("LogoutReceiver.onReceive()") + if (context == null) return + + val accountName = intent?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME, null) ?: return + + val accountManager = AccountManager.get(context) + + val eAccounts = accountManager.getAccountsByType(context.getString(R.string.eelo_account_type)) + + eAccounts.forEach { + if (it.name == accountName) { + // todo: https://developer.android.com/reference/android/accounts/AccountManager#removeAccount(android.accounts.Account,%20android.app.Activity,%20android.accounts.AccountManagerCallback%3Candroid.os.Bundle%3E,%20android.os.Handler) + accountManager.removeAccount(it, null,null, null) + } + } + + // todo https://developer.android.com/reference/android/accounts/AccountManager#startAddAccountSession(java.lang.String,%20java.lang.String,%20java.lang.String[],%20android.os.Bundle,%20android.app.Activity,%20android.accounts.AccountManagerCallback%3Candroid.os.Bundle%3E,%20android.os.Handler) } } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt index e41544d53..4e6f04fe5 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt @@ -34,6 +34,7 @@ object NotificationUtils { const val NOTIFY_SYNC_EXPEDITED = 14 const val NOTIFY_TASKS_PROVIDER_TOO_OLD = 20 const val NOTIFY_PERMISSIONS = 21 + const val NOTIFY_SWITCH_TO_OPENID = 22 const val NOTIFY_LICENSE = 100 -- GitLab From adccf3db647bfb2377cc330e0c1e8b32081a4b25 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 12 Nov 2024 15:53:08 +0100 Subject: [PATCH 04/31] chore: update notification text and remove useless commented code --- .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 5 ----- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 25d0ee1a0..5503fc11c 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -31,7 +31,6 @@ class BootCompletedReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Logger.log.info("Device has been rebooted; checking sync intervals etc.") -// val isOpenIdAvailable = isOpenIdAvailable() val eAccountType = context.getString(R.string.eelo_account_type) val accountManager = AccountManager.get(context) @@ -47,10 +46,6 @@ class BootCompletedReceiver: BroadcastReceiver() { } } } - //TODO will I need it ? -// private fun isOpenIdAvailable(): Boolean { -// return false -// } private fun isLoggedWithOpenId(account: Account, accountManager: AccountManager): Boolean { val hasAuthStateData = accountManager.getUserData(account, AccountSettings.KEY_AUTH_STATE) != null diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e08b3c004..58f63b7dc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -55,7 +55,7 @@ Network and I/O errors Timeouts, connection problems, etc. (often temporary) Your account %1$s - A new login service for a better experience is available. Tap the notification to start using it. + A new login service for a better experience is available. Tap the notification to start using it: you'll be logged out and will simply have to log in again. Your data. Your choice. -- GitLab From c6ddcfd2a69c876c0fd9170945614ff634cd29ce Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 12 Nov 2024 17:44:42 +0100 Subject: [PATCH 05/31] refactor: replace LogoutReceiver by ReLoginWithOidcActivity which has no UI --- app/build.gradle | 3 +- app/src/main/AndroidManifest.xml | 447 ++++++++---------- .../davdroid/ReLoginWithOidcActivity.kt | 63 +++ .../receiver/BootCompletedReceiver.kt | 8 +- .../davdroid/receiver/LogoutReceiver.kt | 31 -- 5 files changed, 278 insertions(+), 274 deletions(-) create mode 100644 app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt delete mode 100644 app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt diff --git a/app/build.gradle b/app/build.gradle index 0904d4364..f23b9754c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,7 +30,7 @@ android { setProperty "archivesBaseName", "davx5-ose-" + getVersionName() - minSdkVersion 24 // Android 7.0 + minSdkVersion 26 // Android 9.0 targetSdkVersion 33 // Android 13 buildConfigField "String", "userAgent", "\"AccountManager\"" @@ -156,6 +156,7 @@ configurations { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin}" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3' + implementation 'androidx.activity:activity:1.9.3' testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2299dfee3..cf503f3c1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,118 +1,168 @@ - + xmlns:tools="http://schemas.android.com/tools" + android:installLocation="internalOnly"> - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - + + + + - - - - + - fine location (Android 10) + --> + + + + + + - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + android:supportsRtl="true" + android:theme="@style/AppTheme" + tools:ignore="UnusedAttribute"> + - + tools:node="remove"> - + - - - - - - + + + - + + + + + android:theme="@style/AppTheme.NoActionBar"> - - + + + - - + android:parentActivityName=".ui.AccountsActivity" + android:theme="@style/AppTheme.NoActionBar" /> + android:parentActivityName=".ui.AccountsActivity"> - + + + android:label="@string/debug_info_title" + android:parentActivityName=".ui.AppSettingsActivity"> - + + @@ -124,43 +174,43 @@ android:name=".ui.TasksActivity" android:label="@string/intro_tasks_title" android:parentActivityName=".ui.AppSettingsActivity" /> - + android:exported="true" + android:label="@string/login_title" + android:parentActivityName=".ui.AccountsActivity"> - + - - - - - - - - + + + + + + + + + + + - - - - + android:theme="@style/AppTheme.NoActionBar"> - + android:parentActivityName=".ui.AccountsActivity" /> - - - - + - + + + android:resource="@xml/account_authenticator" /> - + + + android:resource="@xml/sync_calendars" /> - + + + android:resource="@xml/sync_notes" /> - + + + android:resource="@xml/sync_opentasks" /> - + + + android:resource="@xml/sync_tasks_org" /> + - - - + + android:exported="true"> - + + android:resource="@xml/account_authenticator_address_book" /> + + android:label="@string/address_books_authority_title" /> + - + + android:resource="@xml/sync_address_books" /> - + + android:resource="@xml/sync_contacts" /> - - - + android:resource="@xml/contacts" /> + @@ -313,22 +364,20 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/eelo_account_authenticator" /> - - - + - - - - - - + - - - - - - + - - - - - + @@ -425,7 +466,6 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/account_authenticator_eelo_address_book" /> - - - + - - - + @@ -469,8 +506,7 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/google_account_authenticator" /> - - - - + - - - + @@ -510,7 +543,6 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/account_authenticator_google_address_book" /> - - - + - - - - - + @@ -568,7 +596,6 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/yahoo_account_authenticator" /> - - - - - - + @@ -623,7 +646,6 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/account_authenticator_yahoo_address_book" /> - - - - - - + + + android:exported="false" + android:grantUriPermissions="true"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt new file mode 100644 index 000000000..d53218e97 --- /dev/null +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -0,0 +1,63 @@ +package at.bitfire.davdroid + +import android.accounts.AccountManager +import android.accounts.AccountManager.KEY_BOOLEAN_RESULT +import android.accounts.AccountManagerFuture +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import at.bitfire.davdroid.log.Logger + +class ReLoginWithOidcActivity : AppCompatActivity() { + override fun onStart() { + super.onStart() + + val accountName = intent?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME, null) ?: return + val accountManager = AccountManager.get(this) + + val accountRemovalCallback: (AliasFuture) -> Unit = { future -> + val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) + Logger.log.info("$accountName removal succeed ? $success") + if (success) { + loginAccount(accountManager) + } else { + Logger.log.info("failed to remove account: ${accountName} ") + } + } + + + logoutAccount(accountName, accountManager, accountRemovalCallback) + + + } + + + private fun logoutAccount(accountName: String, + accountManager: AccountManager, + callback : (AliasFuture) -> Unit) + { + val eAccounts= accountManager.getAccountsByType(applicationContext.getString(R.string.eelo_account_type)) + val activity = this + + eAccounts.first { it.name == accountName }.run { + Logger.log.info("try to remove account: ${this.name} ") //todo remove this before merge + accountManager.removeAccount(this, activity, callback, null) + + } ?: finish() + } + + private fun loginAccount(accountManager: AccountManager) { + val eAccountType = applicationContext.getString(R.string.eelo_account_type) + val authTokenType = null + + accountManager.startAddAccountSession(eAccountType, + authTokenType, + arrayOf(), + null, + this, + { _ -> finish() }, + null + ) + } +} + +typealias AliasFuture = AccountManagerFuture \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 5503fc11c..901261ac7 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -13,6 +13,7 @@ import android.content.Intent import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import at.bitfire.davdroid.R +import at.bitfire.davdroid.ReLoginWithOidcActivity import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.AccountUtils @@ -72,13 +73,14 @@ class BootCompletedReceiver: BroadcastReceiver() { } private fun generateLogoutIntent(accountName: String, context: Context): PendingIntent { - val logoutIntent = Intent(context, LogoutReceiver::class.java).apply { + val reloginIntent = Intent(context, ReLoginWithOidcActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK putExtra(AccountManager.KEY_ACCOUNT_NAME, accountName) } - return PendingIntent.getBroadcast(context, + return PendingIntent.getActivity(context, 0, - logoutIntent, + reloginIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) } } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt deleted file mode 100644 index f58d6207e..000000000 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/LogoutReceiver.kt +++ /dev/null @@ -1,31 +0,0 @@ -package at.bitfire.davdroid.receiver - -import android.accounts.Account -import android.accounts.AccountManager -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import at.bitfire.davdroid.R -import at.bitfire.davdroid.log.Logger - -class LogoutReceiver(): BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - Logger.log.info("LogoutReceiver.onReceive()") - if (context == null) return - - val accountName = intent?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME, null) ?: return - - val accountManager = AccountManager.get(context) - - val eAccounts = accountManager.getAccountsByType(context.getString(R.string.eelo_account_type)) - - eAccounts.forEach { - if (it.name == accountName) { - // todo: https://developer.android.com/reference/android/accounts/AccountManager#removeAccount(android.accounts.Account,%20android.app.Activity,%20android.accounts.AccountManagerCallback%3Candroid.os.Bundle%3E,%20android.os.Handler) - accountManager.removeAccount(it, null,null, null) - } - } - - // todo https://developer.android.com/reference/android/accounts/AccountManager#startAddAccountSession(java.lang.String,%20java.lang.String,%20java.lang.String[],%20android.os.Bundle,%20android.app.Activity,%20android.accounts.AccountManagerCallback%3Candroid.os.Bundle%3E,%20android.os.Handler) - } -} \ No newline at end of file -- GitLab From af78d23d938f189bc0628c5619f6e4822cc1b43f Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 12 Nov 2024 17:45:56 +0100 Subject: [PATCH 06/31] change minimum SDK to reach API 26: required to use AccountManager.startAddAccountSessionActivity --- app/src/main/res/values/strings.xml | 2 +- build.gradle | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 58f63b7dc..92854722d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -55,7 +55,7 @@ Network and I/O errors Timeouts, connection problems, etc. (often temporary) Your account %1$s - A new login service for a better experience is available. Tap the notification to start using it: you'll be logged out and will simply have to log in again. + A new login service for a better experience is available. Tap the notification to start using it: you\'ll be logged out and will simply have to log in again. Your data. Your choice. diff --git a/build.gradle b/build.gradle index e969706ab..22f24469e 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,7 @@ buildscript { plugins { // see https://github.com/google/ksp/releases for version numbers id 'com.google.devtools.ksp' version '1.9.10-1.0.13' apply false + id 'org.jetbrains.kotlin.android' version '1.9.10' apply false } allprojects { -- GitLab From 724228fa8314c25120b2056b70e71bb196c4ce67 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 14 Nov 2024 11:00:02 +0100 Subject: [PATCH 07/31] fix: use Notification Utils to create the notification builder & to provide notification channel --- .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 901261ac7..ae213e30a 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -17,6 +17,8 @@ import at.bitfire.davdroid.ReLoginWithOidcActivity import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.settings.AccountSettings import at.bitfire.davdroid.syncadapter.AccountUtils +import at.bitfire.davdroid.ui.NotificationUtils +import at.bitfire.davdroid.ui.NotificationUtils.CHANNEL_GENERAL import at.bitfire.davdroid.ui.NotificationUtils.NOTIFY_SWITCH_TO_OPENID import at.bitfire.davdroid.ui.NotificationUtils.notifyIfPossible @@ -60,7 +62,8 @@ class BootCompletedReceiver: BroadcastReceiver() { val notifText = context.getString(R.string.notification_switch_to_openId_text) val notifIntent = generateLogoutIntent(account.name, context) - val notification = NotificationCompat.Builder(context, "your_channel_id") + + val notification = NotificationUtils.newBuilder(context, CHANNEL_GENERAL) .setContentTitle(notifTitle) .setContentText(notifText) .setSmallIcon(R.drawable.ic_info) -- GitLab From c2d13a1a7a1fd1e64c3137172e5066972d5271f7 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 14 Nov 2024 13:38:04 +0100 Subject: [PATCH 08/31] fix: update notification title & content text --- .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 2 +- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index ae213e30a..95e3f9835 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -58,7 +58,7 @@ class BootCompletedReceiver: BroadcastReceiver() { private fun notifySwitchToOpenId(account: Account, context: Context) { val notifTag = "Switch to openID" - val notifTitle = context.getString(R.string.notification_account_title) + val notifTitle = context.getString(R.string.notification_account_title, account.name) val notifText = context.getString(R.string.notification_switch_to_openId_text) val notifIntent = generateLogoutIntent(account.name, context) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 92854722d..e08b3c004 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -55,7 +55,7 @@ Network and I/O errors Timeouts, connection problems, etc. (often temporary) Your account %1$s - A new login service for a better experience is available. Tap the notification to start using it: you\'ll be logged out and will simply have to log in again. + A new login service for a better experience is available. Tap the notification to start using it. Your data. Your choice. -- GitLab From b0d796fa7c7b2208b35ae1a47468b6cf7a2b0518 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 14 Nov 2024 13:39:46 +0100 Subject: [PATCH 09/31] refactor: rewrite if to check account type in BootCompleteReceiver and update coding style --- .../bitfire/davdroid/ReLoginWithOidcActivity.kt | 15 ++++++--------- .../davdroid/receiver/BootCompletedReceiver.kt | 11 +++++------ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index d53218e97..d25332e92 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -16,21 +16,18 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val accountRemovalCallback: (AliasFuture) -> Unit = { future -> val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) - Logger.log.info("$accountName removal succeed ? $success") + if (success) { + Logger.log.info("Vincent: $accountName removed") loginAccount(accountManager) } else { - Logger.log.info("failed to remove account: ${accountName} ") + Logger.log.info("failed to remove account: $accountName ") } } - logoutAccount(accountName, accountManager, accountRemovalCallback) - - } - private fun logoutAccount(accountName: String, accountManager: AccountManager, callback : (AliasFuture) -> Unit) @@ -39,9 +36,8 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val activity = this eAccounts.first { it.name == accountName }.run { - Logger.log.info("try to remove account: ${this.name} ") //todo remove this before merge + Logger.log.info("Vincent: try to remove account: ${this.name} ") //todo remove this before merge accountManager.removeAccount(this, activity, callback, null) - } ?: finish() } @@ -49,6 +45,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val eAccountType = applicationContext.getString(R.string.eelo_account_type) val authTokenType = null + Logger.log.info("Vincent: Will start add Account Session") accountManager.startAddAccountSession(eAccountType, authTokenType, arrayOf(), @@ -60,4 +57,4 @@ class ReLoginWithOidcActivity : AppCompatActivity() { } } -typealias AliasFuture = AccountManagerFuture \ No newline at end of file +typealias AliasFuture = AccountManagerFuture diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 95e3f9835..9b28bc658 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -10,7 +10,6 @@ import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import at.bitfire.davdroid.R import at.bitfire.davdroid.ReLoginWithOidcActivity @@ -44,7 +43,8 @@ class BootCompletedReceiver: BroadcastReceiver() { val accountSettings = AccountSettings(context, it) accountSettings.initSync() - if (it.type.equals(eAccountType) && !isLoggedWithOpenId(it, accountManager)) { + if (eAccountType == it.type && !isLoggedWithOpenId(it, accountManager)) { + Logger.log.info("Vincent: eAccountFound. Will notify") notifySwitchToOpenId(it, context) } } @@ -62,7 +62,6 @@ class BootCompletedReceiver: BroadcastReceiver() { val notifText = context.getString(R.string.notification_switch_to_openId_text) val notifIntent = generateLogoutIntent(account.name, context) - val notification = NotificationUtils.newBuilder(context, CHANNEL_GENERAL) .setContentTitle(notifTitle) .setContentText(notifText) @@ -76,14 +75,14 @@ class BootCompletedReceiver: BroadcastReceiver() { } private fun generateLogoutIntent(accountName: String, context: Context): PendingIntent { - val reloginIntent = Intent(context, ReLoginWithOidcActivity::class.java).apply { + val reLoginIntent = Intent(context, ReLoginWithOidcActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK putExtra(AccountManager.KEY_ACCOUNT_NAME, accountName) } return PendingIntent.getActivity(context, 0, - reloginIntent, + reLoginIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) } -} \ No newline at end of file +} -- GitLab From ff57c7be58ec24a2ac0c1deb84352d6d37294bbe Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Fri, 15 Nov 2024 10:00:14 +0100 Subject: [PATCH 10/31] feature: Start add account session after logout --- .../davdroid/ReLoginWithOidcActivity.kt | 98 ++++++++++++++++--- 1 file changed, 85 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index d25332e92..5f6cfdb70 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -1,35 +1,67 @@ package at.bitfire.davdroid import android.accounts.AccountManager +import android.accounts.AccountManager.KEY_ACCOUNT_SESSION_BUNDLE import android.accounts.AccountManager.KEY_BOOLEAN_RESULT +import android.accounts.AccountManager.KEY_INTENT import android.accounts.AccountManagerFuture +import android.accounts.AuthenticatorException +import android.content.Intent +import android.os.Build import android.os.Bundle +import android.os.PersistableBundle +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import at.bitfire.davdroid.log.Logger +import com.owncloud.android.lib.common.operations.OperationCancelledException +import java.io.IOException class ReLoginWithOidcActivity : AppCompatActivity() { + + private lateinit var addAccountLauncher: ActivityResultLauncher + private lateinit var accountManager : AccountManager + private var sessionBundle: Bundle? = null + + override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { + super.onCreate(savedInstanceState, persistentState) + + accountManager = AccountManager.get(this) + // Initialize the ActivityResultLauncher + addAccountLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + result -> + if (result.resultCode == RESULT_OK) { + // Account was added successfully + // Handle the result here + accountManager.finishSession(sessionBundle, + null, { _ -> + Logger.log.info("Vincent: Account added") + finish() + }, null) + } + } + } + override fun onStart() { super.onStart() val accountName = intent?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME, null) ?: return - val accountManager = AccountManager.get(this) val accountRemovalCallback: (AliasFuture) -> Unit = { future -> val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) if (success) { Logger.log.info("Vincent: $accountName removed") - loginAccount(accountManager) + loginAccount() } else { Logger.log.info("failed to remove account: $accountName ") } } - logoutAccount(accountName, accountManager, accountRemovalCallback) + logoutAccount(accountName, accountRemovalCallback) } private fun logoutAccount(accountName: String, - accountManager: AccountManager, callback : (AliasFuture) -> Unit) { val eAccounts= accountManager.getAccountsByType(applicationContext.getString(R.string.eelo_account_type)) @@ -38,22 +70,62 @@ class ReLoginWithOidcActivity : AppCompatActivity() { eAccounts.first { it.name == accountName }.run { Logger.log.info("Vincent: try to remove account: ${this.name} ") //todo remove this before merge accountManager.removeAccount(this, activity, callback, null) + } ?: finish() } - private fun loginAccount(accountManager: AccountManager) { + private fun loginAccount() { val eAccountType = applicationContext.getString(R.string.eelo_account_type) val authTokenType = null Logger.log.info("Vincent: Will start add Account Session") - accountManager.startAddAccountSession(eAccountType, - authTokenType, - arrayOf(), - null, - this, - { _ -> finish() }, - null - ) + + try { + //todo only work for API 33 ? + accountManager.startAddAccountSession( + eAccountType, + authTokenType, + arrayOf(), + null, + this, + { future -> startAddAccount(future) }, + null + ) + } catch (exception: AuthenticatorException) { + Logger.log.info("Vincent: AuthenticatorException: can't add account: ${exception.message}") + + } catch (exception: IOException) { + Logger.log.info("Vincent: IOException: can't add account: ${exception.message}") + } catch (exception: OperationCancelledException) { + Logger.log.info("Vincent: OperationCancelledException: can't add account: ${exception.message}") + } + } + + + private fun startAddAccount(future: AliasFuture) { + try { + val intent: Intent? + + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + intent = future.result.getParcelable(KEY_INTENT, Intent::class.java) + sessionBundle = future.result.getParcelable(KEY_ACCOUNT_SESSION_BUNDLE, Bundle::class.java) + } else { + intent = future.result.getParcelable(KEY_INTENT) + sessionBundle = future.result.getParcelable(KEY_ACCOUNT_SESSION_BUNDLE) + } + + if (sessionBundle == null) { + Logger.log.info("Vincent: session bundle is null") + } + + + intent?.let { + addAccountLauncher.launch(it) + } + } catch (exception: Exception) { + Logger.log.info("Vincent: StartAddAccount: exception: ${exception.message}") + } } } -- GitLab From ca6f8cfe184ddbe8c60389f7cbef9379b93d1056 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Fri, 15 Nov 2024 10:53:33 +0100 Subject: [PATCH 11/31] fix: fix exception thrown because of accountManager --- .../main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 5f6cfdb70..94068a50d 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -20,13 +20,12 @@ import java.io.IOException class ReLoginWithOidcActivity : AppCompatActivity() { private lateinit var addAccountLauncher: ActivityResultLauncher - private lateinit var accountManager : AccountManager private var sessionBundle: Bundle? = null override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { super.onCreate(savedInstanceState, persistentState) - accountManager = AccountManager.get(this) + val accountManager = AccountManager.get(this) // Initialize the ActivityResultLauncher addAccountLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> @@ -64,6 +63,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private fun logoutAccount(accountName: String, callback : (AliasFuture) -> Unit) { + val accountManager = AccountManager.get(this) val eAccounts= accountManager.getAccountsByType(applicationContext.getString(R.string.eelo_account_type)) val activity = this @@ -75,6 +75,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { } private fun loginAccount() { + val accountManager = AccountManager.get(this) val eAccountType = applicationContext.getString(R.string.eelo_account_type) val authTokenType = null -- GitLab From 875ea6cbb2abcee65ccb775a07781a043e0a2730 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Fri, 15 Nov 2024 11:04:44 +0100 Subject: [PATCH 12/31] refactor: prevent syncing /e/ account on murena.io if account is logged with password --- .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 9b28bc658..c79b544f1 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -40,12 +40,12 @@ class BootCompletedReceiver: BroadcastReceiver() { // sync intervals are checked in App.onCreate() AccountUtils.getMainAccounts(context) .forEach { - val accountSettings = AccountSettings(context, it) - accountSettings.initSync() - if (eAccountType == it.type && !isLoggedWithOpenId(it, accountManager)) { Logger.log.info("Vincent: eAccountFound. Will notify") notifySwitchToOpenId(it, context) + } else { + val accountSettings = AccountSettings(context, it) + accountSettings.initSync() } } } -- GitLab From ff08ff3b595de6037883e76bc36f6a2976eead2a Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 20 Nov 2024 10:20:46 +0100 Subject: [PATCH 13/31] refactor: rewrite the ReLoginWithOidcActivity to use AccountManager.addAccount and clean code style and add licence header --- .../davdroid/ReLoginWithOidcActivity.kt | 108 ++++++------------ 1 file changed, 35 insertions(+), 73 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 94068a50d..13523bbb4 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -1,17 +1,19 @@ +/*************************************************************************************************** + * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details. + **************************************************************************************************/ + package at.bitfire.davdroid import android.accounts.AccountManager -import android.accounts.AccountManager.KEY_ACCOUNT_SESSION_BUNDLE +import android.accounts.AccountManager.KEY_ACCOUNT_NAME import android.accounts.AccountManager.KEY_BOOLEAN_RESULT import android.accounts.AccountManager.KEY_INTENT import android.accounts.AccountManagerFuture import android.accounts.AuthenticatorException +import android.content.ActivityNotFoundException import android.content.Intent import android.os.Build import android.os.Bundle -import android.os.PersistableBundle -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import at.bitfire.davdroid.log.Logger import com.owncloud.android.lib.common.operations.OperationCancelledException @@ -19,82 +21,55 @@ import java.io.IOException class ReLoginWithOidcActivity : AppCompatActivity() { - private lateinit var addAccountLauncher: ActivityResultLauncher - private var sessionBundle: Bundle? = null - - override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { - super.onCreate(savedInstanceState, persistentState) - - val accountManager = AccountManager.get(this) - // Initialize the ActivityResultLauncher - addAccountLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { - result -> - if (result.resultCode == RESULT_OK) { - // Account was added successfully - // Handle the result here - accountManager.finishSession(sessionBundle, - null, { _ -> - Logger.log.info("Vincent: Account added") - finish() - }, null) - } - } - } - override fun onStart() { super.onStart() - val accountName = intent?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME, null) ?: return + val accountName = intent?.extras?.getString(KEY_ACCOUNT_NAME, null) ?: return + logoutAccount(accountName) + } + + private fun logoutAccount(accountName: String) + { + val accountManager = AccountManager.get(this) + val eAccountType = applicationContext.getString(R.string.eelo_account_type) + val eAccounts = accountManager.getAccountsByType(eAccountType) - val accountRemovalCallback: (AliasFuture) -> Unit = { future -> + val callback: (AliasFuture) -> Unit = { future -> val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) if (success) { - Logger.log.info("Vincent: $accountName removed") - loginAccount() + loginAccount(eAccountType) } else { Logger.log.info("failed to remove account: $accountName ") } } - logoutAccount(accountName, accountRemovalCallback) - } - - private fun logoutAccount(accountName: String, - callback : (AliasFuture) -> Unit) - { - val accountManager = AccountManager.get(this) - val eAccounts= accountManager.getAccountsByType(applicationContext.getString(R.string.eelo_account_type)) val activity = this - eAccounts.first { it.name == accountName }.run { - Logger.log.info("Vincent: try to remove account: ${this.name} ") //todo remove this before merge + eAccounts.firstOrNull() { + it.name == accountName + } ?.run { accountManager.removeAccount(this, activity, callback, null) - } ?: finish() } - private fun loginAccount() { + private fun loginAccount(accountType: String) { val accountManager = AccountManager.get(this) - val eAccountType = applicationContext.getString(R.string.eelo_account_type) - val authTokenType = null Logger.log.info("Vincent: Will start add Account Session") try { - //todo only work for API 33 ? - accountManager.startAddAccountSession( - eAccountType, - authTokenType, - arrayOf(), + accountManager.addAccount( + accountType, + null, null, - this, - { future -> startAddAccount(future) }, + null, + null, //todo: choose between this & null + { future -> startAddAccountActivity(future) }, null ) } catch (exception: AuthenticatorException) { Logger.log.info("Vincent: AuthenticatorException: can't add account: ${exception.message}") - } catch (exception: IOException) { Logger.log.info("Vincent: IOException: can't add account: ${exception.message}") } catch (exception: OperationCancelledException) { @@ -102,29 +77,16 @@ class ReLoginWithOidcActivity : AppCompatActivity() { } } + private fun startAddAccountActivity(future: AliasFuture) { + val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + future.result.getParcelable(KEY_INTENT, Intent::class.java) + } else { + future.result.getParcelable(KEY_INTENT) + } ?: return - private fun startAddAccount(future: AliasFuture) { try { - val intent: Intent? - - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - intent = future.result.getParcelable(KEY_INTENT, Intent::class.java) - sessionBundle = future.result.getParcelable(KEY_ACCOUNT_SESSION_BUNDLE, Bundle::class.java) - } else { - intent = future.result.getParcelable(KEY_INTENT) - sessionBundle = future.result.getParcelable(KEY_ACCOUNT_SESSION_BUNDLE) - } - - if (sessionBundle == null) { - Logger.log.info("Vincent: session bundle is null") - } - - - intent?.let { - addAccountLauncher.launch(it) - } - } catch (exception: Exception) { + startActivity(intent) + } catch (exception: ActivityNotFoundException) { Logger.log.info("Vincent: StartAddAccount: exception: ${exception.message}") } } -- GitLab From 29335d53d197d47bedbd3d1c4bcad9c0b48da100 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 20 Nov 2024 11:43:44 +0100 Subject: [PATCH 14/31] refactor: change way to add an account and clean code style again --- .../davdroid/ReLoginWithOidcActivity.kt | 44 ++++++++----------- .../receiver/BootCompletedReceiver.kt | 2 - 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 13523bbb4..20e52f657 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -7,24 +7,20 @@ package at.bitfire.davdroid import android.accounts.AccountManager import android.accounts.AccountManager.KEY_ACCOUNT_NAME import android.accounts.AccountManager.KEY_BOOLEAN_RESULT -import android.accounts.AccountManager.KEY_INTENT import android.accounts.AccountManagerFuture -import android.accounts.AuthenticatorException -import android.content.ActivityNotFoundException -import android.content.Intent -import android.os.Build import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import at.bitfire.davdroid.log.Logger -import com.owncloud.android.lib.common.operations.OperationCancelledException -import java.io.IOException class ReLoginWithOidcActivity : AppCompatActivity() { override fun onStart() { super.onStart() - val accountName = intent?.extras?.getString(KEY_ACCOUNT_NAME, null) ?: return + val accountName = intent?.extras?.getString(KEY_ACCOUNT_NAME, null) ?: run { + finish() + return + } logoutAccount(accountName) } @@ -56,39 +52,35 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private fun loginAccount(accountType: String) { val accountManager = AccountManager.get(this) - Logger.log.info("Vincent: Will start add Account Session") - try { accountManager.addAccount( accountType, null, null, null, - null, //todo: choose between this & null + this, { future -> startAddAccountActivity(future) }, null ) - } catch (exception: AuthenticatorException) { - Logger.log.info("Vincent: AuthenticatorException: can't add account: ${exception.message}") - } catch (exception: IOException) { - Logger.log.info("Vincent: IOException: can't add account: ${exception.message}") - } catch (exception: OperationCancelledException) { - Logger.log.info("Vincent: OperationCancelledException: can't add account: ${exception.message}") + } catch (exception: Exception) { + Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") } } private fun startAddAccountActivity(future: AliasFuture) { - val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - future.result.getParcelable(KEY_INTENT, Intent::class.java) - } else { - future.result.getParcelable(KEY_INTENT) - } ?: return + val result = future.result?: run { + Logger.log.warning("Can't add new account: future.result is null") + finish() + return + } - try { - startActivity(intent) - } catch (exception: ActivityNotFoundException) { - Logger.log.info("Vincent: StartAddAccount: exception: ${exception.message}") + val accountName = result.getString(KEY_ACCOUNT_NAME) + val accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE, "invalidAccountType") + + if (accountName != null) { + Logger.log.info("($accountType) account added: $accountName") } + finish() } } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index c79b544f1..7818384ba 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -34,14 +34,12 @@ class BootCompletedReceiver: BroadcastReceiver() { Logger.log.info("Device has been rebooted; checking sync intervals etc.") val eAccountType = context.getString(R.string.eelo_account_type) - val accountManager = AccountManager.get(context) // sync intervals are checked in App.onCreate() AccountUtils.getMainAccounts(context) .forEach { if (eAccountType == it.type && !isLoggedWithOpenId(it, accountManager)) { - Logger.log.info("Vincent: eAccountFound. Will notify") notifySwitchToOpenId(it, context) } else { val accountSettings = AccountSettings(context, it) -- GitLab From 993b1c94cff7b894a039c52f0fd5a12a6bf34c94 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 20 Nov 2024 12:53:22 +0100 Subject: [PATCH 15/31] refactor: remove useless callback --- .../bitfire/davdroid/ReLoginWithOidcActivity.kt | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 20e52f657..392107a50 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -59,27 +59,13 @@ class ReLoginWithOidcActivity : AppCompatActivity() { null, null, this, - { future -> startAddAccountActivity(future) }, + null, null ) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") } - } - - private fun startAddAccountActivity(future: AliasFuture) { - val result = future.result?: run { - Logger.log.warning("Can't add new account: future.result is null") - finish() - return - } - val accountName = result.getString(KEY_ACCOUNT_NAME) - val accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE, "invalidAccountType") - - if (accountName != null) { - Logger.log.info("($accountType) account added: $accountName") - } finish() } } -- GitLab From 1b2627ecbf366febb04c57ce9d87ba15200156fe Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 20 Nov 2024 16:15:19 +0100 Subject: [PATCH 16/31] fix: try to fix account not kept at the end --- .../davdroid/ReLoginWithOidcActivity.kt | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 392107a50..ed399d0c6 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -7,13 +7,18 @@ package at.bitfire.davdroid import android.accounts.AccountManager import android.accounts.AccountManager.KEY_ACCOUNT_NAME import android.accounts.AccountManager.KEY_BOOLEAN_RESULT +import android.accounts.AccountManager.KEY_INTENT import android.accounts.AccountManagerFuture +import android.content.Intent +import android.os.Build import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import at.bitfire.davdroid.log.Logger class ReLoginWithOidcActivity : AppCompatActivity() { + private var needLogout = true + override fun onStart() { super.onStart() @@ -21,7 +26,11 @@ class ReLoginWithOidcActivity : AppCompatActivity() { finish() return } - logoutAccount(accountName) + + Logger.log.info("Vincent: onStart() call and gonna logout account") + if (needLogout) { + logoutAccount(accountName) + } } private fun logoutAccount(accountName: String) @@ -34,6 +43,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) if (success) { + needLogout = false loginAccount(eAccountType) } else { Logger.log.info("failed to remove account: $accountName ") @@ -52,21 +62,33 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private fun loginAccount(accountType: String) { val accountManager = AccountManager.get(this) + val callback: (AliasFuture) -> Unit = { future -> + val intent = getIntentFromFuture(future) + intent?.let(::startActivity) + finish() + } + try { accountManager.addAccount( accountType, null, null, null, - this, null, + { future -> callback(future)}, null ) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") } + } - finish() + private fun getIntentFromFuture(future: AliasFuture): Intent? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + future.result?.getParcelable(KEY_INTENT, Intent::class.java) + } else { + future.result?.getParcelable(KEY_INTENT) + } } } -- GitLab From aa4d27e0d2935a400430525e379d8ff167bd21af Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 20 Nov 2024 16:38:28 +0100 Subject: [PATCH 17/31] fix: try something else --- .../davdroid/ReLoginWithOidcActivity.kt | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index ed399d0c6..f51925102 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -17,8 +17,6 @@ import at.bitfire.davdroid.log.Logger class ReLoginWithOidcActivity : AppCompatActivity() { - private var needLogout = true - override fun onStart() { super.onStart() @@ -26,11 +24,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { finish() return } - - Logger.log.info("Vincent: onStart() call and gonna logout account") - if (needLogout) { logoutAccount(accountName) - } } private fun logoutAccount(accountName: String) @@ -43,7 +37,6 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) if (success) { - needLogout = false loginAccount(eAccountType) } else { Logger.log.info("failed to remove account: $accountName ") @@ -62,12 +55,6 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private fun loginAccount(accountType: String) { val accountManager = AccountManager.get(this) - val callback: (AliasFuture) -> Unit = { future -> - val intent = getIntentFromFuture(future) - intent?.let(::startActivity) - finish() - } - try { accountManager.addAccount( accountType, @@ -75,20 +62,13 @@ class ReLoginWithOidcActivity : AppCompatActivity() { null, null, null, - { future -> callback(future)}, + null, null ) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") } - } - - private fun getIntentFromFuture(future: AliasFuture): Intent? { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - future.result?.getParcelable(KEY_INTENT, Intent::class.java) - } else { - future.result?.getParcelable(KEY_INTENT) - } + finish() } } -- GitLab From a42d22e4e5eebb18a008a9e6e3e3aa7c5ca9aafc Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 20 Nov 2024 16:55:52 +0100 Subject: [PATCH 18/31] Revert "fix: try something else" This reverts commit aa4d27e0d2935a400430525e379d8ff167bd21af. --- .../davdroid/ReLoginWithOidcActivity.kt | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index f51925102..ed399d0c6 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -17,6 +17,8 @@ import at.bitfire.davdroid.log.Logger class ReLoginWithOidcActivity : AppCompatActivity() { + private var needLogout = true + override fun onStart() { super.onStart() @@ -24,7 +26,11 @@ class ReLoginWithOidcActivity : AppCompatActivity() { finish() return } + + Logger.log.info("Vincent: onStart() call and gonna logout account") + if (needLogout) { logoutAccount(accountName) + } } private fun logoutAccount(accountName: String) @@ -37,6 +43,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) if (success) { + needLogout = false loginAccount(eAccountType) } else { Logger.log.info("failed to remove account: $accountName ") @@ -55,6 +62,12 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private fun loginAccount(accountType: String) { val accountManager = AccountManager.get(this) + val callback: (AliasFuture) -> Unit = { future -> + val intent = getIntentFromFuture(future) + intent?.let(::startActivity) + finish() + } + try { accountManager.addAccount( accountType, @@ -62,13 +75,20 @@ class ReLoginWithOidcActivity : AppCompatActivity() { null, null, null, - null, + { future -> callback(future)}, null ) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") } - finish() + } + + private fun getIntentFromFuture(future: AliasFuture): Intent? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + future.result?.getParcelable(KEY_INTENT, Intent::class.java) + } else { + future.result?.getParcelable(KEY_INTENT) + } } } -- GitLab From 152b6353bf9a0e2c3ca2c750e52102312c7181ed Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 21 Nov 2024 09:35:35 +0100 Subject: [PATCH 19/31] chore: add debug instruction --- .../davdroid/ReLoginWithOidcActivity.kt | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index ed399d0c6..df8b753a2 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -17,10 +17,9 @@ import at.bitfire.davdroid.log.Logger class ReLoginWithOidcActivity : AppCompatActivity() { - private var needLogout = true - override fun onStart() { super.onStart() + Logger.log.info("Vincent: onStart()") val accountName = intent?.extras?.getString(KEY_ACCOUNT_NAME, null) ?: run { finish() @@ -28,9 +27,17 @@ class ReLoginWithOidcActivity : AppCompatActivity() { } Logger.log.info("Vincent: onStart() call and gonna logout account") - if (needLogout) { - logoutAccount(accountName) - } + logoutAccount(accountName) + } + + override fun onStop() { + super.onStop() + Logger.log.info("Vincent: onStop()") + } + + override fun onDestroy() { + super.onDestroy() + Logger.log.info("Vincent: onDestroy()") } private fun logoutAccount(accountName: String) @@ -43,7 +50,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) if (success) { - needLogout = false + Logger.log.info("Vincent: Account removed. Now will sign in again with OIDC") loginAccount(eAccountType) } else { Logger.log.info("failed to remove account: $accountName ") @@ -55,6 +62,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { eAccounts.firstOrNull() { it.name == accountName } ?.run { + Logger.log.info("Vincent: about to call accountManager.removeAccount") accountManager.removeAccount(this, activity, callback, null) } ?: finish() } @@ -64,7 +72,9 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val callback: (AliasFuture) -> Unit = { future -> val intent = getIntentFromFuture(future) + Logger.log.info("Vincent: callback for login account. About to start intent(is null ?: ${intent == null})") intent?.let(::startActivity) + Logger.log.info("Vincent: callback for login account. Intent started. About to finish ${this.javaClass}") finish() } -- GitLab From 5fdf8a4327226bcbf7d0d4d302f4110c75b8f684 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 21 Nov 2024 14:31:07 +0100 Subject: [PATCH 20/31] chore: try to disable flags --- .../main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt | 5 +++++ .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index df8b753a2..257647059 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -51,9 +51,12 @@ class ReLoginWithOidcActivity : AppCompatActivity() { if (success) { Logger.log.info("Vincent: Account removed. Now will sign in again with OIDC") + + //todo: open Login activity without android AccountManager loginAccount(eAccountType) } else { Logger.log.info("failed to remove account: $accountName ") + //todo call a finish } } @@ -90,7 +93,9 @@ class ReLoginWithOidcActivity : AppCompatActivity() { ) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") + //todo call finish } + } private fun getIntentFromFuture(future: AliasFuture): Intent? { diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 7818384ba..363fafcff 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -74,7 +74,7 @@ class BootCompletedReceiver: BroadcastReceiver() { private fun generateLogoutIntent(accountName: String, context: Context): PendingIntent { val reLoginIntent = Intent(context, ReLoginWithOidcActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + //flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK putExtra(AccountManager.KEY_ACCOUNT_NAME, accountName) } -- GitLab From 28655c605571e1103cbf324b4fdf6ec5cbe4578a Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Fri, 22 Nov 2024 11:43:02 +0100 Subject: [PATCH 21/31] chore: try to fix fix PendingIntent.FLAG_ONE_SHOT --- .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 363fafcff..4e3337751 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -81,6 +81,6 @@ class BootCompletedReceiver: BroadcastReceiver() { return PendingIntent.getActivity(context, 0, reLoginIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT) } } -- GitLab From c1eb2d14383f93fd807ca86d0b6bcd7ee84194f7 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Mon, 25 Nov 2024 09:32:19 +0100 Subject: [PATCH 22/31] fix: update manifest to avoid ReLoginWithOidcActivity to be in recent activities --- app/src/main/AndroidManifest.xml | 6 +++++- .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cf503f3c1..a6e99595a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -103,9 +103,13 @@ android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="UnusedAttribute"> + + android:taskAffinity="" + android:excludeFromRecents="true" + android:exported="false" /> + Date: Mon, 25 Nov 2024 13:16:47 +0100 Subject: [PATCH 23/31] fix: add immutable flag for pending intent --- .../at/bitfire/davdroid/receiver/BootCompletedReceiver.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 271d5051e..7818384ba 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -81,6 +81,6 @@ class BootCompletedReceiver: BroadcastReceiver() { return PendingIntent.getActivity(context, 0, reLoginIntent, - PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) } } -- GitLab From ba200223ac1a9afc807d98b6aab2a6c876c1f332 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 27 Nov 2024 11:20:34 +0100 Subject: [PATCH 24/31] fix: try to fix the bug with finish & recent activities --- app/src/main/AndroidManifest.xml | 2 -- .../davdroid/ReLoginWithOidcActivity.kt | 28 ++++++++----------- .../receiver/BootCompletedReceiver.kt | 3 +- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a6e99595a..3a69080a3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -106,8 +106,6 @@ diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 257647059..a5f6e09b5 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -12,11 +12,14 @@ import android.accounts.AccountManagerFuture import android.content.Intent import android.os.Build import android.os.Bundle +import android.os.Handler +import android.os.Looper import androidx.appcompat.app.AppCompatActivity import at.bitfire.davdroid.log.Logger class ReLoginWithOidcActivity : AppCompatActivity() { + override fun onStart() { super.onStart() Logger.log.info("Vincent: onStart()") @@ -26,20 +29,9 @@ class ReLoginWithOidcActivity : AppCompatActivity() { return } - Logger.log.info("Vincent: onStart() call and gonna logout account") logoutAccount(accountName) } - override fun onStop() { - super.onStop() - Logger.log.info("Vincent: onStop()") - } - - override fun onDestroy() { - super.onDestroy() - Logger.log.info("Vincent: onDestroy()") - } - private fun logoutAccount(accountName: String) { val accountManager = AccountManager.get(this) @@ -51,12 +43,12 @@ class ReLoginWithOidcActivity : AppCompatActivity() { if (success) { Logger.log.info("Vincent: Account removed. Now will sign in again with OIDC") - - //todo: open Login activity without android AccountManager loginAccount(eAccountType) } else { - Logger.log.info("failed to remove account: $accountName ") - //todo call a finish + Logger.log.info("failed to remove account: $accountName") + Handler(Looper.getMainLooper()).post { + finish() + } } } @@ -78,7 +70,9 @@ class ReLoginWithOidcActivity : AppCompatActivity() { Logger.log.info("Vincent: callback for login account. About to start intent(is null ?: ${intent == null})") intent?.let(::startActivity) Logger.log.info("Vincent: callback for login account. Intent started. About to finish ${this.javaClass}") - finish() + Handler(Looper.getMainLooper()).post { + finish() + } } try { @@ -93,7 +87,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { ) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") - //todo call finish + finish() } } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt index 7818384ba..67b9e0ecf 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/receiver/BootCompletedReceiver.kt @@ -81,6 +81,7 @@ class BootCompletedReceiver: BroadcastReceiver() { return PendingIntent.getActivity(context, 0, reLoginIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT or + PendingIntent.FLAG_ONE_SHOT) } } -- GitLab From 5f680480eb4a39f91dda499eb644b3d0f10a2e98 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Wed, 27 Nov 2024 14:24:32 +0100 Subject: [PATCH 25/31] refactor: rewrite ReLoginWithOidcActivity --- .../davdroid/ReLoginWithOidcActivity.kt | 65 ++++++++++++------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index a5f6e09b5..6700dcce3 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -4,6 +4,7 @@ package at.bitfire.davdroid +import android.accounts.Account import android.accounts.AccountManager import android.accounts.AccountManager.KEY_ACCOUNT_NAME import android.accounts.AccountManager.KEY_BOOLEAN_RESULT @@ -19,6 +20,15 @@ import at.bitfire.davdroid.log.Logger class ReLoginWithOidcActivity : AppCompatActivity() { + private lateinit var eAccountType: String + private lateinit var accountManager: AccountManager + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + eAccountType = applicationContext.getString(R.string.eelo_account_type) + accountManager = AccountManager.get(this) + } override fun onStart() { super.onStart() @@ -29,67 +39,68 @@ class ReLoginWithOidcActivity : AppCompatActivity() { return } - logoutAccount(accountName) + val account = getAccount(accountName) + + if (isAccountRemoved && account == null) { + Logger.log.info("Vincent: call loginAccount()") + loginAccount(eAccountType) + } else if (!isAccountRemoved && account != null) { + Logger.log.info("Vincent: call logoutAccount()") + logoutAccount(account) + } else { + finish() + } } - private fun logoutAccount(accountName: String) - { - val accountManager = AccountManager.get(this) - val eAccountType = applicationContext.getString(R.string.eelo_account_type) + private fun getAccount(accountName: String) : Account? { val eAccounts = accountManager.getAccountsByType(eAccountType) + return eAccounts.firstOrNull { it.name == accountName } + } + + private fun logoutAccount(account: Account) + { val callback: (AliasFuture) -> Unit = { future -> val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) if (success) { + isAccountRemoved = true Logger.log.info("Vincent: Account removed. Now will sign in again with OIDC") loginAccount(eAccountType) } else { - Logger.log.info("failed to remove account: $accountName") + Logger.log.info("failed to remove /e/OS account") Handler(Looper.getMainLooper()).post { finish() } } } - val activity = this - - eAccounts.firstOrNull() { - it.name == accountName - } ?.run { + try { Logger.log.info("Vincent: about to call accountManager.removeAccount") - accountManager.removeAccount(this, activity, callback, null) - } ?: finish() + accountManager.removeAccount(account, this, callback, null) + } catch (exception: Exception) { + Logger.log.warning("Cannot remove account: ${account.name} : ${exception.message}") + } } private fun loginAccount(accountType: String) { - val accountManager = AccountManager.get(this) val callback: (AliasFuture) -> Unit = { future -> val intent = getIntentFromFuture(future) - Logger.log.info("Vincent: callback for login account. About to start intent(is null ?: ${intent == null})") intent?.let(::startActivity) Logger.log.info("Vincent: callback for login account. Intent started. About to finish ${this.javaClass}") + Handler(Looper.getMainLooper()).post { finish() } } try { - accountManager.addAccount( - accountType, - null, - null, - null, - null, - { future -> callback(future)}, - null - ) + accountManager.addAccount(accountType,null, null, null, null, callback, null) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") finish() } - } private fun getIntentFromFuture(future: AliasFuture): Intent? { @@ -99,6 +110,10 @@ class ReLoginWithOidcActivity : AppCompatActivity() { future.result?.getParcelable(KEY_INTENT) } } + + companion object { + private var isAccountRemoved = false + } } typealias AliasFuture = AccountManagerFuture -- GitLab From 5d9bbe79f6d547ab647b241026dbae0f1977140f Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 28 Nov 2024 09:44:02 +0100 Subject: [PATCH 26/31] fix: replace finish() by finishAdnRemoveTask() --- .../java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 6700dcce3..b9ebe839e 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -48,7 +48,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { Logger.log.info("Vincent: call logoutAccount()") logoutAccount(account) } else { - finish() + finishAndRemoveTask() } } @@ -70,7 +70,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { } else { Logger.log.info("failed to remove /e/OS account") Handler(Looper.getMainLooper()).post { - finish() + finishAndRemoveTask() } } } @@ -80,6 +80,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { accountManager.removeAccount(account, this, callback, null) } catch (exception: Exception) { Logger.log.warning("Cannot remove account: ${account.name} : ${exception.message}") + finishAndRemoveTask() } } @@ -91,7 +92,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { Logger.log.info("Vincent: callback for login account. Intent started. About to finish ${this.javaClass}") Handler(Looper.getMainLooper()).post { - finish() + finishAndRemoveTask() } } @@ -99,7 +100,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { accountManager.addAccount(accountType,null, null, null, null, callback, null) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") - finish() + finishAndRemoveTask() } } -- GitLab From da413daaef5ce662ff220d5995953e85177f34f1 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 28 Nov 2024 10:38:25 +0100 Subject: [PATCH 27/31] chore: small tunings to make it works --- .../davdroid/ReLoginWithOidcActivity.kt | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index b9ebe839e..aa4fb9ac4 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -87,9 +87,13 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private fun loginAccount(accountType: String) { val callback: (AliasFuture) -> Unit = { future -> - val intent = getIntentFromFuture(future) - intent?.let(::startActivity) - Logger.log.info("Vincent: callback for login account. Intent started. About to finish ${this.javaClass}") + val accountName = future.result?.getString(KEY_ACCOUNT_NAME) + if (accountName != null) { + Logger.log.info("Account $accountName logged again") + } else { + Logger.log.warning("No new account relogged") + } + Handler(Looper.getMainLooper()).post { finishAndRemoveTask() @@ -97,21 +101,13 @@ class ReLoginWithOidcActivity : AppCompatActivity() { } try { - accountManager.addAccount(accountType,null, null, null, null, callback, null) + accountManager.addAccount(accountType,null, null, null, this, callback, null) } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") finishAndRemoveTask() } } - private fun getIntentFromFuture(future: AliasFuture): Intent? { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - future.result?.getParcelable(KEY_INTENT, Intent::class.java) - } else { - future.result?.getParcelable(KEY_INTENT) - } - } - companion object { private var isAccountRemoved = false } -- GitLab From 0e21929f45b03619810c2b8bb77d3205f4fa0e44 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 28 Nov 2024 11:04:57 +0100 Subject: [PATCH 28/31] fix: move try catch in the correct block --- .../davdroid/ReLoginWithOidcActivity.kt | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index aa4fb9ac4..3a2fb8a01 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -61,51 +61,49 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private fun logoutAccount(account: Account) { val callback: (AliasFuture) -> Unit = { future -> - val success = future.result.getBoolean(KEY_BOOLEAN_RESULT) + + val success = try { + future.result.getBoolean(KEY_BOOLEAN_RESULT) + } catch (exception: Exception) { + Logger.log.warning("Cannot remove account: ${account.name} : ${exception.message}") + false + } if (success) { isAccountRemoved = true Logger.log.info("Vincent: Account removed. Now will sign in again with OIDC") loginAccount(eAccountType) } else { - Logger.log.info("failed to remove /e/OS account") Handler(Looper.getMainLooper()).post { finishAndRemoveTask() } } } - try { - Logger.log.info("Vincent: about to call accountManager.removeAccount") - accountManager.removeAccount(account, this, callback, null) - } catch (exception: Exception) { - Logger.log.warning("Cannot remove account: ${account.name} : ${exception.message}") - finishAndRemoveTask() - } + Logger.log.info("Vincent: about to call accountManager.removeAccount") + accountManager.removeAccount(account, this, callback, null) } private fun loginAccount(accountType: String) { val callback: (AliasFuture) -> Unit = { future -> - val accountName = future.result?.getString(KEY_ACCOUNT_NAME) - if (accountName != null) { - Logger.log.info("Account $accountName logged again") - } else { - Logger.log.warning("No new account relogged") + try { + val accountName = future.result?.getString(KEY_ACCOUNT_NAME) + if (accountName != null) { + Logger.log.info("Vincent: Account $accountName logged again") + } else { + Logger.log.warning("Vincent: No new account relogged") + } + } catch (exception: Exception) { + Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") } - Handler(Looper.getMainLooper()).post { finishAndRemoveTask() } } - try { - accountManager.addAccount(accountType,null, null, null, this, callback, null) - } catch (exception: Exception) { - Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") - finishAndRemoveTask() - } + accountManager.addAccount(accountType,null, null, null, this, callback, null) } companion object { -- GitLab From 4c607a683a7354b391bb96e7908fe9763ea2242b Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 28 Nov 2024 11:26:47 +0100 Subject: [PATCH 29/31] chore: remove debug logging --- .../bitfire/davdroid/ReLoginWithOidcActivity.kt | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 3a2fb8a01..ba26cee0d 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -32,20 +32,18 @@ class ReLoginWithOidcActivity : AppCompatActivity() { override fun onStart() { super.onStart() - Logger.log.info("Vincent: onStart()") val accountName = intent?.extras?.getString(KEY_ACCOUNT_NAME, null) ?: run { - finish() + finishAndRemoveTask() return } val account = getAccount(accountName) if (isAccountRemoved && account == null) { - Logger.log.info("Vincent: call loginAccount()") loginAccount(eAccountType) + } else if (!isAccountRemoved && account != null) { - Logger.log.info("Vincent: call logoutAccount()") logoutAccount(account) } else { finishAndRemoveTask() @@ -71,7 +69,7 @@ class ReLoginWithOidcActivity : AppCompatActivity() { if (success) { isAccountRemoved = true - Logger.log.info("Vincent: Account removed. Now will sign in again with OIDC") + Logger.log.info("Account removed. Now will sign in again with OIDC") loginAccount(eAccountType) } else { Handler(Looper.getMainLooper()).post { @@ -79,8 +77,6 @@ class ReLoginWithOidcActivity : AppCompatActivity() { } } } - - Logger.log.info("Vincent: about to call accountManager.removeAccount") accountManager.removeAccount(account, this, callback, null) } @@ -89,10 +85,8 @@ class ReLoginWithOidcActivity : AppCompatActivity() { val callback: (AliasFuture) -> Unit = { future -> try { val accountName = future.result?.getString(KEY_ACCOUNT_NAME) - if (accountName != null) { - Logger.log.info("Vincent: Account $accountName logged again") - } else { - Logger.log.warning("Vincent: No new account relogged") + if (accountName == null) { + Logger.log.warning("No account re-added") } } catch (exception: Exception) { Logger.log.warning("${exception.javaClass}: can't add account: ${exception.message}") -- GitLab From 04f607e5da0ca9bb6ac0c8919055e76075236a93 Mon Sep 17 00:00:00 2001 From: Vincent Bourgmayer Date: Thu, 28 Nov 2024 13:33:42 +0000 Subject: [PATCH 30/31] Apply Jonathan's suggestion --- .../main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index ba26cee0d..21049e1cf 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -42,7 +42,6 @@ class ReLoginWithOidcActivity : AppCompatActivity() { if (isAccountRemoved && account == null) { loginAccount(eAccountType) - } else if (!isAccountRemoved && account != null) { logoutAccount(account) } else { @@ -55,7 +54,6 @@ class ReLoginWithOidcActivity : AppCompatActivity() { return eAccounts.firstOrNull { it.name == accountName } } - private fun logoutAccount(account: Account) { val callback: (AliasFuture) -> Unit = { future -> -- GitLab From d2d3b0bb2747c600a56bef3f0612147ee3910245 Mon Sep 17 00:00:00 2001 From: Vincent Bourgmayer Date: Thu, 28 Nov 2024 13:43:17 +0000 Subject: [PATCH 31/31] fix:Apply Jonathan's suggestion --- app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt index 21049e1cf..607b1dcc9 100644 --- a/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ReLoginWithOidcActivity.kt @@ -23,7 +23,6 @@ class ReLoginWithOidcActivity : AppCompatActivity() { private lateinit var eAccountType: String private lateinit var accountManager: AccountManager - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) eAccountType = applicationContext.getString(R.string.eelo_account_type) -- GitLab