Blog Infos
Author
Published
Topics
, , ,
Published

Compose Multiplatform and FirebaseCompose Multiplatform and Firebase logos (Source: JetBrains & Google, used under their brand guidelines)

Trying to hook Firebase into a KMP project? You’ve probably noticed there’s no one‐click solution (or official SDK). Firebase remains essential for authentication, real-time data, and crash reporting.

In this tutorial, you will learn how to:

  • Configure and set up multiple Firebase environments for a KMP app
  • Use Cocoapod iOS libraries within Kotlin
  • Use Kotlin code from Swift
  • Have a Kotlin Multiplatform app with full Firebase support
Before you continue

If you’re looking for prebuilt libraries, check out these wonderful solutions!

Check out the code as we progress or use it as a base for your project.

Setup

This tutorial was built with these tools and assumes you have them as well.

1: Create a Kotlin Multiplatform project in Android Studio

Inside Android Studio, click New Project and select Kotlin Multiplatform. You will need the Kotlin Multiplatform Plugin to see this option. You can also use the KMP Wizard to generate a project.

Selecting Kotlin MultiplatformSelecting Kotlin Multiplatform

Continue through the flow. In this example, the UI will be shared.

Shared UI for an Android and iOS AppShared UI for an Android and iOS App

2: Create Dev & Prod Firebase Projects

Log in to your Firebase console and create two projects. One development/staging project and another production project.

At the end, you should see something like this

Two Firebase projects

Two Firebase projects

Set up Android and iOS for both projects

Next, set up your Android and iOS apps in Firebase for each project. Then download each config file. In this tutorial, I suffixed the bundle id with “dev” for development environments. Example:

  • com.medium.authtutorial.dev (Development)
  • com.medium.authtutorial (Production)

You should have two of each file, one for development and one for production. Put all in the same folder and suffix them with the environment they use. Example:

  • google-services-development.json
  • google-services-production.json
  • GoogleService-Info-Development.plist
  • GoogleService-Info-Production.plist
3: Configure Firebase on Android (Gradle + JSON)

In this part, we’ll add the Firebase BOM and optional libraries to androidMain. Firebase auto-initializes on Android, so this will be short and sweet.

Add the required libraries

To get Firebase up and running, add these libraries.

[versions]
firebase-bom = "33.14.0"
google-services-plugin = "4.4.2"
[libraries]
android-firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" }
# Optional, include if using firebase auth
android-firebase-auth = { module = "com.google.firebase:firebase-auth" }
# Optional, include if using firebase analytics
android-firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
[plugins]
googleServices = { id = "com.google.gms.google-services", version.ref = "google-services-plugin" }
Link to the Android source set

Remember, these libraries are not built for KMP, so you have to add them to androidMain, not commonMain.

plugins {
// Other plugins
alias(libs.plugins.googleServices)
}
sourceSets {
androidMain.dependencies {
implementation(compose.preview)
implementation(libs.androidx.activity.compose)
implementation(project.dependencies.platform(libs.android.firebase.bom))
implementation(libs.android.firebase.auth)
implementation(libs.android.firebase.analytics)
}
// etc
}

Sync your project and make sure there are no errors.

Add google-service.json to your project

We need Android to locate our JSON file so that Firebase can auto-initialize.

  1. Under /composeApp/src, create two folders: debug and release.
  2. Your google-service.jsonfiles into their respective folders. If you renamed it, make sure to name it back to google-service.json
Add google-services.json to debug and release folders

Add google-services.json to debug and release folders

Change the bundle id depending on the environment

Remember, we are setting up Firebase for a development and production environment. If you don’t change the bundle id to match your google-services.json, Firebase may not initialize.

Inside of build.gradle.kts, let’s make it so our debug app appends the dev bundle id.

android {
// Other configurations...
buildTypes {
getByName("debug") {
isMinifyEnabled = false
applicationIdSuffix = ".dev"
versionNameSuffix = "-DEBUG"
}
getByName("release") {
isMinifyEnabled = true
}
}
}
Launch!

On Android, Firebase initializes automatically. So launch your app and check logcat! If you made it this far, 👏 and pat yourself on the back. You’re halfway there!

Successful Firebase Initialization on AndroidSuccessful Firebase Initialization on Android

4: Set up Firebase in iOS (CocoaPods + Kotlin)

In this section, we will initialize iOS Firebase using Kotlin, how exciting! This is due to the power of CocoaPods in our KMP app.

It’s time to become familiar with the iosApp folder. This is where your native iOS application lives. The other folder, iosMain, contains all your iOS Kotlin code. It’s recommended to use the Project view to see this folder inside Android Studio.

Use the Project view to see the iosApp directory

Link GoogleService-Info.plist into your iOS App

Firebase needs to link to the right GoogleService-Info.plist file, which we will do in this section. For now, do the following:

  1. Navigate to the top iosApp folder and make a directory called Firebase
  2. Drag and drop your two GoogleService-Info files into it

You should end up with something like this.

iOS Firebase filesiOS Firebase files

Set up environment configuration files

Our Xcode project comes with a configuration file located in /Configuration/Config.xcconfig. But we need two config files. One for debug and one for production. This will help us load the correct GoogleService file.

  1. Navigate to /iosApp/Configuration
  2. Duplicate Config.xcconfig
  3. Name one Debug.xcconfig and the other Release.xcconfig
  4. Configure both of these files to your heart’s content
  5. Finally, add a new variable GOOGLE_SERVICE and set it depending on your environment.

GOOGLE_SERVICE=$(SRCROOT)/Firebase/GoogleService-Info-Production.plist

GOOGLE_SERVICE=$(SRCROOT)/Firebase/GoogleService-Info-Development.plist

Link the configuration files inside Xcode

We now need our project to read these new configuration files. We can change this in the project view.

  1. Open your xcproject file in Xcode
  2. Click iosApp in the top left
  3. Click iosApp under project
  4. Set the Debug.xcconfig and Release.xcconfig for each environment

Setting the xcconfig based on the build environmentSetting the xcconfig based on the build environment

⚠️ At this point, you will not see iosApp populated with the Pods-iosApp.xcconfig. That will happen automatically after completing step 4.7

Set up a build script to copy GoogleService-Info.plist

Firebase expects the file to be called GoogleService-Info.plist. If we try to initialize Firebase with our current file names, we will crash. To fix this

  1. Under Targets, click iosApp
  2. Click the + icon and add a New Run Script Phase
  3. Add the following script
echo "Copying GoogleService located at ${GOOGLE_SERVICE}"
if [ -z "${GOOGLE_SERVICE}" ]; then
echo "GOOGLE_SERVICE is unset or set to the empty string"
exit 1
fi
if [ ! -f "${GOOGLE_SERVICE}" ]; then
echo "GOOGLE_SERVICE does not exist"
exit 1
fi
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist
cp "${GOOGLE_SERVICE}" "${PLIST_DESTINATION}"
echo "Copied ${GOOGLE_SERVICE} to ${PLIST_DESTINATION}"

This script will fail your builds if the GOOGLE_SERVICE variable isn’t found or if it’s blank. Additionally, it will copy the correct plist file into your app.

Adding the GoogleService copying script to Build PhasesAdding the GoogleService copying script to Build Phases

Run the app and verify you can build it before continuing.

Remove the embedAndSign task from the Build Phases

While we are in this view, we need to remove a pre-generated script that is incompatible when using Cocoapods for KMP. That script is called “Compile Kotlin Framework”.

Delete the Compile Kotlin Framework script

Delete the Compile Kotlin Framework script

 

If you don’t remove this, your will get the fatal error “embedAndSign task can not be used in a project with dependencies to pods”.

Back to Android Studio, add the required libraries

Phew! The iOS setup is almost complete. Next, to use CocoaPods in Kotlin, we need to add the plugin to our libs.versions.toml

[plugins]
kotlinCocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" }

Make sure to wire it up in build.gradle.ktslike other plugins!

plugins {
    // Other plugins
    alias(libs.plugins.kotlinCocoapods)
}

If you attempt to sync, you will encounter the error “Cocoapods Integration requires pod version to be specified.” We will resolve this in the next step!

Add the CocoaPods block

Inside of build.gradle.kts, add the CocoaPods block and add the Firebase Core dependency. This will allow us to use iOS Firebase from Kotlin.

// Use the built in cocoapods support to bring in firebase libraries
kotlin {
// Remove the framework block if its here
iosX64()
iosArm64()
iosSimulatorArm64()
cocoapods {
summary = "My compose multiplatform app"
version = "1.0"
homepage = "https://medium.com"
ios.deploymentTarget = "16.0"
// Add the framework block here
framework {
baseName = "ComposeApp"
isStatic = true
}
pod("FirebaseCore") {
version = "~> 11.13"
extraOpts += listOf("-compiler-option", "-fmodules")
}
}
}

Verify that this creates the composeApp.podspec file in your composeApp module.

Create the Podfile in iosApp

Time to link our iOS Kotlin code back to our iOS app. In the iosApp directory, create a new Podfile and paste the content below.

target 'iosApp' do
  use_frameworks!
  platform :ios, '16.0'
  pod 'composeApp', :path => '../composeApp'
end

Next, run a pod install where the Podfile is. If you’ve done everything right, your directory will look similar to this

Configuration, Firebase, Podfile

Configuration, Firebase, Podfile

⚠️ Going forward, only use the xcworkspace file. If you have Xcode open, close it and re-open the project with xcworkspace. Do not use the xcodeproj.

Accept the plugin notification to use the xcworkspace file

Back inside Android Studio, you should see a notification to switch to the xcworkspace file. This is very important, make sure you do this! This will enable us to use Kotlin interop with our CocoaPods.

Accept the KMP plugin prompt to use the workspace

If you do not see the prompt above, try running a pod deintegrate and pod install again. Without this, you will not be able to use CocoaPods inside of Kotlin.

Initializing Firebase for iOS inside Kotlin

We are in the final home stretch! If we attempt to launch our iOS app through Android Studio or Xcode, we should see this error.

The default Firebase app has not yet been configured. Add FirebaseApp.configure() to your application initialization. This can be done in the App Delegate’s application(_:didFinishLaunchingWithOptions:)….

Firebase does not auto-initialize on iOS, unlike on Android. Let’s follow best practices by hooking into didFinishLaunchingWithOptions and initializing Firebase.

Inside the iosMain source set (Kotlin code that interacts with iOS), make a new file called KMPInitializer.kt. Inside, write a simple function that configures Firebase.

import cocoapods.FirebaseCore.FIRApp
import kotlinx.cinterop.ExperimentalForeignApi
@OptIn(ExperimentalForeignApi::class)
fun onDidFinishLaunchingWithOptions() {
println("KMP Initializer: Starting setup...")
FIRApp.configure() // Call Firebase configure
println("KMP Initializer: Firebase project ID: ${FIRApp.defaultApp()?.options!!.projectID()}")
}

As you see, we can use the iOS Firebase SDK from Kotlin. Neat!

Create the AppDelegate.swift file and wire it up

Now, we need to call this function from Swift as there isn’t support for making an app delegates from Kotlin yet.

Inside iosApp (not iosMain), make a new file called AppDelegate.swift. This will be used to hook into critical app operations. Such as startup, teardown, and push notifications.

import Foundation
import UIKit
import ComposeApp
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print("AppDelegate: didFinishLaunchingWithOptions - Calling KMP init.")
// Call your kmp initializer kotlin code!
KMPInitializerKt.onDidFinishLaunchingWithOptions()
return true
}
// You can add other AppDelegate methods here if needed (like push notifications)
}

Finally, link the delegate inside your app’s entry point.

@main
struct iOSApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
view raw iOSApp.swift hosted with ❤ by GitHub

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

,

When sharing isn’t caring: Using platform-specific code in Kotlin Multiplatform

Sharing code across platforms is a wonderful superpower. But sometimes, sharing 100% of your codebase isn’t the goal. Maybe you’re migrating existing apps to multiplatform, maybe you have platform-specific libraries or APIs you want to…
Watch Video

When sharing isn’t caring: Using platform-specific code in Kotlin Multiplatform

Russell Wolf
Kotlin Multiplatform Developer

When sharing isn’t caring: Using platform-specific code in Kotlin Multiplatform

Russell Wolf
Kotlin Multiplatform ...

When sharing isn’t caring: Using platform-specific code in Kotlin Multiplatform

Russell Wolf
Kotlin Multiplatform Deve ...

Jobs

Launch your app and watch the console output. If successful, you should see something like this

iOS Firebase initialized from KotlinSuccessful iOS Firebase initialization using Kotlin

Next Steps

In the following tutorial, we will be integrating Firebase Authentication. This will allow users on iOS and Android to log in, a staple for any app. I will link that article here once it’s posted!

Closing Remarks

That’s it! We’ve successfully linked Firebase to our iOS and Android apps using Kotlin Multiplatform. You now have a template to start your KMP journey using Firebase products.

Check out the source code for this project or connect with me on LinkedIn!

If you found this helpful, leave me a 👏! If you have any comments or feedback, let me know. If you’d like to see a tutorial on anything else, please don’t hesitate to ask. Take care!

This article was previously published on proandroiddev.com.

Menu