Exploring Firebase Authentication in Compose Multiplatform | by means of DeveloperSpace | Jan, 2024

SQLDelight, an impressive Kotlin library for writing platform-agnostic SQL queries, joins forces with caching to create a dynamic duo that elevates your app’s potency. Right here might be storing the refreshToken which we can get from the reaction of login & signUp API name. So subsequent time when consumer opens app, it gained’t ask for authentication.

Setup SQLDelight Dependencies

First you wish to have so as to add required SQLDelight dependencies and plugins in libs.variations.toml record inside of gradle folder.

[versions]
...
...
sqlDelight = "2.0.1"

[libraries]
...
...
sqldelight-androidDriver = { module = "app.money.sqldelight:android-driver", model.ref = "sqlDelight" }
sqldelight-jvmDriver = { module = "app.money.sqldelight:sqlite-driver", model.ref = "sqlDelight" }
sqldelight-nativeDriver = { module = "app.money.sqldelight:native-driver", model.ref = "sqlDelight" }
sqldelight-coroutines = { module = "app.money.sqldelight:coroutines-extensions", model.ref = "sqlDelight" }
sqldelight-primitiveAdapters = { module = "app.money.sqldelight:coroutines-extensions", model.ref = "sqlDelight" }

[plugins]
androidApplication = { identification = "com.android.software", model.ref = "agp" }
androidLibrary = { identification = "com.android.library", model.ref = "agp" }
jetbrainsCompose = { identification = "org.jetbrains.compose", model.ref = "compose-plugin" }
kotlinMultiplatform = { identification = "org.jetbrains.kotlin.multiplatform", model.ref = "kotlin" }
kotlinxSerialization = { identification = "org.jetbrains.kotlin.plugin.serialization", model.ref = "kotlin" }
sqlDelight = { identification = "app.money.sqldelight", model.ref = "sqlDelight" }

Subsequent step is so as to add plugin in project-level construct.gradle.kts record

plugins {
// that is vital to keep away from the plugins to be loaded more than one instances
// in every subproject's classloader
alias(libs.plugins.androidApplication) observe false
alias(libs.plugins.androidLibrary) observe false
alias(libs.plugins.jetbrainsCompose) observe false
alias(libs.plugins.kotlinMultiplatform) observe false
//SQLDelight Plugin
alias(libs.plugins.sqlDelight) observe false
}

In the end, you wish to have to configure SQLDelight in composeApp construct.gradle.kts record. Right here we can upload dependencies in response to the desired platform and upload identify of SQLDelight database. You are going to see sqlDelight block on the finish which can include a listing of databases and their parameter

import org.jetbrains.compose.ExperimentalComposeLibrary
import org.jetbrains.compose.desktop.software.dsl.TargetFormat

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.kotlinxSerialization)
alias(libs.plugins.sqlDelight)
}

kotlin {

androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "1.8"
}
}
}

jvm("desktop")

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp"
// This must be set to false to run on iOS
isStatic = false
// Upload it to keep away from sqllite3 problems in iOS
linkerOpts.upload("-lsqlite3")
}
}

sourceSets {
val desktopMain by means of getting

androidMain.dependencies {
implementation(libs.compose.ui.tooling.preview)
implementation(libs.androidx.task.compose)
implementation(libs.ktor.shopper.okhttp)
//SqlDelight for Android
implementation(libs.sqldelight.androidDriver)
}
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.basis)
implementation(compose.subject material)
implementation(compose.ui)
@OptIn(ExperimentalComposeLibrary::magnificence)
implementation(compose.elements.assets)
//Ktor
implementation(libs.ktor.shopper.core)
implementation(libs.ktor.shopper.content material.negotiation)
implementation(libs.ktor.serialization.kotlinx.json)
//Moko MVVM
implementation(libs.moko.mvvm.core)
implementation(libs.moko.mvvm.compose)
//Kamel
implementation(libs.kamel)
// Navigator
implementation(libs.voyager.navigator)
//SqlDelight for not unusual
implementation(libs.sqldelight.coroutines)
implementation(libs.sqldelight.primitiveAdapters)
}
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutines.swing)
implementation(libs.ktor.shopper.okhttp)
//SqlDelight for jvm
implementation(libs.sqldelight.jvmDriver)
}
iosMain.dependencies {
//SqlDelight for iOS
implementation(libs.sqldelight.nativeDriver)
}
}
}

sqldelight {
databases {
//Notice: Title of your Database and .sq record must be similar
create("Database") {
packageName.set("com.dwarshb.firebaseauthentication")
}
}
// Upload this line to keep away from library linking problems
linkSqlite = true
}

android {
...
}

compose.desktop {
...
}

Create Database.sq record for Queries

Subsequent step is to create .sq record.which can include the entire wanted SQL queries. Via default, the SQLDelight plugin reads .sq from the programs folder in sqldelight folder which might be immediately inside of commainMain folder.
Please take a look at beneath Screenshot of Folder Construction the place Database.sq record is positioned.

In case your bundle identify is com.instance.projectName, then your Database.sq record must be positioned inside of commonMain/sqldelight/com/instance/projectName/Database.sq

Upload beneath code inside of your Database.sq record which accommodates queries equivalent to createTable, insertUser, removeAllUsers and getAllUsers

After the assignment is compiled, the generated Kotlin code might be saved within the composeApp/construct/generated/sqldelight listing. Or else you’ll be able to additionally use ./gradlew generateSqlDelightInterface command in terminal to generate sqldelight kotlin code.

Create database drivers

SQLDelight supplies more than one platform-specific implementations of the SQLite motive force, so you wish to have to create them for every platform one at a time. You’ll be able to do that by means of the use of anticipated and exact declarations.

In composeApp/src/commonMain/kotlin create the bundle and inside of it create DriverFactory.kt magnificence

bundle com.dwarshb.firebaseauthentication

import app.money.sqldelight.db.SqlDriver

be expecting magnificence DriverFactory {
a laugh createDriver(): SqlDriver
}

Now we want to put in force this for every goal platform.

On Android, the AndroidSqliteDriver magnificence implements the SQLite motive force.
So, in composeApp/src/androidMain/kotlin create the bundle and inside of it create DriverFactory.kt magnificence

bundle com.dwarshb.firebaseauthentication

import android.content material.Context
import app.money.sqldelight.db.SqlDriver
import app.money.sqldelight.motive force.android.AndroidSqliteDriver

exact magnificence DriverFactory(var appContext: Context) {

exact a laugh createDriver(): SqlDriver {
go back AndroidSqliteDriver(Database.Schema, appContext, "firebase.db")
}
}

Now you wish to have to create its example in MainActivity.kt record to be had in composeApp/src/androidMain/kotlin to make it paintings for Android.


magnificence MainActivity : ComponentActivity() {
override a laugh onCreate(savedInstanceState: Package deal?) {
tremendous.onCreate(savedInstanceState)
//Create example of DriverFactory for Android
val driverFactory = DriverFactory(this)
setContent {
App(driverFactory.createDriver())
}
}
}

On iOS, the SQLite motive force implementation is the NativeSqliteDriver magnificence.
So, in composeApp/src/iosMain/kotlin create the bundle and inside of it create DriverFactory.kt magnificence

bundle com.dwarshb.firebaseauthentication

import app.money.sqldelight.db.SqlDriver
import app.money.sqldelight.motive force.local.NativeSqliteDriver

exact magnificence DriverFactory {
exact a laugh createDriver(): SqlDriver {
go back NativeSqliteDriver(Database.Schema, "firebase.db")
}
}

Now you wish to have to create its example in MainViewController.kt record to be had in composeApp/src/iosMain/kotlin to make it paintings for iOS.

import androidx.compose.ui.window.ComposeUIViewController
import com.dwarshb.firebaseauthentication.DriverFactory

a laugh MainViewController() = ComposeUIViewController {
val driverFactory = DriverFactory()
App(driverFactory.createDriver())
}

On Desktop, the SQLite motive force implementation is the JdbcSqliteDriver magnificence.
So, in composeApp/src/desktopMain/kotlin create the bundle and inside of it create DriverFactory.kt magnificence

bundle com.dwarshb.firebaseauthentication

import app.money.sqldelight.db.SqlDriver
import app.money.sqldelight.motive force.jdbc.sqlite.JdbcSqliteDriver
import java.io.Document

exact magnificence DriverFactory {
exact a laugh createDriver(): SqlDriver {
val databasePath = Document(Gadget.getProperty("java.io.tmpdir"), "firebase.db")
val motive force: SqlDriver = JdbcSqliteDriver(url = "jdbc:sqlite:${databasePath.absolutePath}")
Database.Schema.create(motive force)
go back motive force
}
}

Now you wish to have to create its example in major.kt record to be had in composeApp/src/desktopMain/kotlin to make it paintings for Desktop.

import androidx.compose.ui.window.Window
import androidx.compose.ui.window.software
import com.dwarshb.firebaseauthentication.DriverFactory

a laugh major() = software {
Window(onCloseRequest = ::exitApplication, name = "FirebaseAuthentication") {
val driverFactory = DriverFactory()
App(driverFactory.createDriver())
}
}

Leave a Comment

Your email address will not be published. Required fields are marked *