Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92c8cf0a authored by Mohammed Althaf T's avatar Mohammed Althaf T 😊
Browse files

AM: Add Murena account support

parent 7754f4c3
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -5,6 +5,10 @@ stages:
  - build

before_script:
  - echo MURENA_CLIENT_ID=$MURENA_CLIENT_ID >> local.properties
  - echo MURENA_REDIRECT_URI=$MURENA_REDIRECT_URI >> local.properties
  - echo MURENA_BASE_URL=$MURENA_BASE_URL >> local.properties
  - echo MURENA_DISCOVERY_END_POINT=$MURENA_DISCOVERY_END_POINT >> local.properties
  - export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
  - export GRADLE_USER_HOME=$(pwd)/.gradle
  - chmod +x ./gradlew
+15 −2
Original line number Diff line number Diff line
import java.io.FileInputStream
import java.io.FileOutputStream
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Properties
@@ -94,6 +92,12 @@ android {
            if (versionName != null) {
                setProperty("archivesBaseName", "AccountManager-$versionName")
            }

            manifestPlaceholders.putAll(
                mapOf<String, Any>(
                    "murenaAuthRedirectScheme" to retrieveKey("MURENA_REDIRECT_URI"),
                )
            )
        }
    }

@@ -148,6 +152,15 @@ android {
    }
}

fun retrieveKey(keyName: String): String {
    val properties = Properties().apply {
        load(rootProject.file("local.properties").inputStream())
    }

    return properties.getProperty(keyName)
        ?: throw GradleException("$keyName property not found in local.properties file")
}

dependencies {
    // include core subproject (manages its own dependencies itself, however from same version catalog)
    implementation(project(":core"))
+185 −0
Original line number Diff line number Diff line
@@ -5,6 +5,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />

    <uses-permission android:name="foundation.e.permission.READ_TASKS"/>
    <uses-permission android:name="foundation.e.permission.WRITE_TASKS"/>

    <application>

        <!-- AppAuth login flow redirect -->
@@ -19,9 +27,186 @@
                    tools:ignore="AppLinkUrlError"
                        android:scheme="${applicationId}"
                    android:path="/oauth2/redirect"/>

                <!-- /e/ Specific -->
                <data android:scheme="${applicationId}" />
                <data android:scheme="${murenaAuthRedirectScheme}" />
            </intent-filter>
        </activity>

        <!-- region /e/ Specific -->
        <service
                android:name=".sync.adapter.MurenaCalendarsSyncAdapterService"
                android:exported="true"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>
            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_calendars"/>
        </service>

        <service
                android:name=".sync.adapter.MurenaJtxSyncAdapterService"
                android:exported="true"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>
            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_notes"/>
        </service>

        <service
                android:name=".sync.adapter.MurenaOpenTasksSyncAdapterService"
                android:exported="true"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>
            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_opentasks"/>
        </service>

        <service
                android:name=".sync.adapter.MurenaEOpenTasksSyncAdapterService"
                android:exported="true"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>
            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_e_opentasks"/>
        </service>

        <service
                android:name=".sync.adapter.MurenaTasksOrgSyncAdapterService"
                android:exported="true"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>
            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_tasks_org"/>
        </service>

        <service
                android:name="foundation.e.accountmanager.sync.account.MurenaAccountAuthenticatorService"
                android:exported="false">
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator"/>
            </intent-filter>
            <meta-data
                    android:name="android.accounts.AccountAuthenticator"
                    android:resource="@xml/murena_account_authenticator"/>
        </service>

        <service
                android:name="foundation.e.accountmanager.sync.account.MurenaAddressBookAuthenticatorService"
                android:exported="true"
                tools:ignore="ExportedService">   <!-- Since Android 11, this must be true so that Google Contacts shows the address book accounts -->
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator"/>
            </intent-filter>

            <meta-data
                    android:name="android.accounts.AccountAuthenticator"
                    android:resource="@xml/murena_account_authenticator_address_book"/>
        </service>

        <service
                android:name=".sync.adapter.MurenaContactsSyncAdapterService"
                android:exported="true"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter"/>
            </intent-filter>

            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_contacts"/>
            <meta-data
                    android:name="android.provider.CONTACTS_STRUCTURE"
                    android:resource="@xml/contacts"/>
        </service>

        <service
                android:name=".sync.adapter.MurenaMeteredEdriveSyncAdapterService"
                android:exported="true"
                android:process=":sync"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter" />
            </intent-filter>

            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_metered_edrive" />
        </service>

        <service
                android:name=".sync.adapter.MurenaMediaSyncAdapterService"
                android:exported="true"
                android:process=":sync"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter" />
            </intent-filter>

            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_media" />
        </service>

        <service
                android:name=".sync.adapter.MurenaAppDataSyncAdapterService"
                android:exported="true"
                android:process=":sync"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter" />
            </intent-filter>

            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_app_data" />
        </service>

        <service
                android:name=".sync.adapter.MurenaEmailSyncAdapterService"
                android:exported="true"
                android:process=":sync"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter" />
            </intent-filter>

            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_email" />
        </service>

        <service
                android:name=".sync.adapter.MurenaNotesSyncAdapterService"
                android:exported="true"
                android:process=":sync"
                tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.content.SyncAdapter" />
            </intent-filter>

            <meta-data
                    android:name="android.content.SyncAdapter"
                    android:resource="@xml/e_sync_e_notes" />
        </service>

        <!-- endregion /e/ Specific -->

    </application>

</manifest>
 No newline at end of file
+17 −0
Original line number Diff line number Diff line
import java.util.Properties

/*
 * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
 */
@@ -22,6 +24,11 @@ android {

        // include these rules in the app that uses the core library
        consumerProguardFile("core-proguard-rules.pro")

        buildConfigField("String", "MURENA_CLIENT_ID", "\"${retrieveKey("MURENA_CLIENT_ID")}\"")
        buildConfigField("String", "MURENA_REDIRECT_URI", "\"${retrieveKey("MURENA_REDIRECT_URI")}\"")
        buildConfigField("String", "MURENA_BASE_URL", "\"${retrieveKey("MURENA_BASE_URL")}\"")
        buildConfigField("String", "MURENA_DISCOVERY_END_POINT", "\"${retrieveKey("MURENA_DISCOVERY_END_POINT")}\"")
    }

    java {
@@ -84,6 +91,15 @@ android {
    }
}

fun retrieveKey(keyName: String): String {
    val properties = Properties().apply {
        load(rootProject.file("local.properties").inputStream())
    }

    return properties.getProperty(keyName)
        ?: throw GradleException("$keyName property not found in local.properties file")
}

ksp {
    arg("room.schemaLocation", "$projectDir/schemas")
}
@@ -180,6 +196,7 @@ dependencies {
    implementation(libs.commons.lang)

    // e-Specific dependencies
    implementation(libs.androidx.runtime.livedata)
    implementation(libs.elib)
    implementation(libs.ez.vcard)
    implementation(libs.synctools) {
+3 −3
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ class AccountSettings @AssistedInject constructor(
            *AccountTypes.getAccountTypes().toTypedArray(),
            "at.bitfire.davdroid.test"      // R.strings.account_type_test in androidTest
        )
        if (!allowedAccountTypes.contains(account.type))
        if (!allowedAccountTypes.any { it == account.type })
            throw IllegalArgumentException("Invalid account type for AccountSettings(): ${account.type}")

        // synchronize because account migration must only be run one time
@@ -157,7 +157,7 @@ class AccountSettings @AssistedInject constructor(
            SyncDataType.CONTACTS -> KEY_SYNC_INTERVAL_ADDRESSBOOKS
            SyncDataType.EVENTS -> KEY_SYNC_INTERVAL_CALENDARS
            SyncDataType.TASKS -> KEY_SYNC_INTERVAL_TASKS
            SyncDataType.DEFAULT -> KEY_SYNC_INTERVAL_DEFAULT
            else -> KEY_SYNC_INTERVAL_DEFAULT
        }
        val seconds = accountManager.getUserData(account, key)?.toLong()
        return when (seconds) {
@@ -178,7 +178,7 @@ class AccountSettings @AssistedInject constructor(
            SyncDataType.CONTACTS -> KEY_SYNC_INTERVAL_ADDRESSBOOKS
            SyncDataType.EVENTS -> KEY_SYNC_INTERVAL_CALENDARS
            SyncDataType.TASKS -> KEY_SYNC_INTERVAL_TASKS
            SyncDataType.DEFAULT -> KEY_SYNC_INTERVAL_DEFAULT
            else -> KEY_SYNC_INTERVAL_DEFAULT
        }
        val newValue = seconds ?: SYNC_INTERVAL_MANUALLY
        accountManager.setAndVerifyUserData(account, key, newValue.toString())
Loading