Formation Android

TP5

Prérequis: Terminez au moins l’étape “Refactor: UserViewModel” du TP precedent

On va maintenant rendre l’app plus proche d’une app réelle en permettant de se logger au lieu d’avoir un token en dur

Login / Sign up

OAuth

<activity
    android:name="org.publicvalue.multiplatform.oidc.appsupport.HandleRedirectActivity"
    android:exported="true">
    <intent-filter tools:node="removeAll" />
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data
            android:host="cyrilfind.kodo"
            android:scheme="https"
            android:path="/redirect_uri" />
    </intent-filter>
</activity>
val codeAuthFlowFactory = AndroidCodeAuthFlowFactory()
val oAuthClient = OpenIdConnectClient {
    endpoints {
        authorizationEndpoint = "https://todoist.com/oauth/authorize"
        tokenEndpoint = "https://todoist.com/oauth/access_token"
    }

    clientId = "a9400191c656400fb31a043e530c5522"
    clientSecret = "198815c02ac94f029a00338135a45123"
    scope = "task:add,data:read_write,data:delete"
    redirectUri = "https://cyrilfind.kodo/redirect_uri"
}

Login

fun login() {
 // ...
 val tokenResponse = codeAuthFlowFactory.createAuthFlow(oAuthClient).getAccessToken()
 val token = tokenResponse.access_token
 // ...
}

Preference DataStore

Pour l’instant le soucis c’est que vous devez vous reconnecter à chaque lancement de l’app, on va y remédier en utilisant un stockage qui dure au delà d’une session d’utilisation de l’app.


private val Context.userDatastore by preferencesDataStore("user")

class TokenRepository(val context: Context) {
    private val key = stringPreferencesKey("token")

    val tokenFlow = context.userDatastore.data.map { ... }

    suspend fun store(token: String) {
        context.userDatastore.edit { ... }
    }

    suspend fun clear() {
        context.userDatastore.edit { ... }
    }
}

Injection de dépendance

Repository

Refactorisez toute l’app pour que vos écrans ne récupèrent qu’un objet “state”, et remontent seulement des évènements vers des ViewModel qui eux même interrogent des Repository partagés.

Interfaces

Tests unitaires