Creating a new Firebase SDK
Want to create a new SDK in firebase/firebase-android-sdk? Read on.
Repository layout and Gradle
firebase/firebase-android-sdk uses a multi-project Gradle build to organize the different libraries it hosts. As a consequence, each project/product within this repo is hosted under its own subdirectory with its respective build file(s).
firebase-android-sdk
├── buildSrc
├── appcheck
│ └── firebase-appcheck
│ └── firebase-appcheck-playintegrity
├── firebase-annotations
├── firebase-common
│ └── firebase-common.gradle # note the name of the build file
│ └── ktx
│ └── ktx.gradle.kts # it can also be kts
└── build.gradle # root project build file.
Most commonly, SDKs are located as immediate child directories of the root directory, with the directory name being the exact name of the Maven artifact ID the library will have once released. e.g. firebase-common
directory hosts code for the com.google.firebase:firebase-common
SDK.
Note that the build file name for any given SDK is not build.gradle
or build.gradle.kts
but rather mirrors the name of the sdk, e.g. firebase-common/firebase-common.gradle
or firebase-common/firebase-common.gradle.kts
.
All of the core Gradle build logic lives in buildSrc
and is used by all SDKs.
SDKs can be grouped together for convenience by placing them in a directory of choice.
Creating an SDK
Let’s say you want to create an SDK named firebase-foo
- Create a directory called
firebase-foo
. - Create a file
firebase-foo/firebase-foo.gradle.kts
. - Add
firebase-foo
line tosubprojects.cfg
at the root of the tree.
Update firebase-foo.gradle.kts
with the following content
firebase-foo.gradle.kts
plugins {
id("firebase-library")
// Uncomment for Kotlin
// id("kotlin-android")
}
firebaseLibrary {
// enable this only if you have tests in `androidTest`.
testLab.enabled = true
publishSources = true
publishJavadoc = true
}
android {
val targetSdkVersion : Int by rootProject
val minSdkVersion : Int by rootProject
compileSdk = targetSdkVersion
defaultConfig {
namespace = "com.google.firebase.foo"
// change this if you have custom needs.
minSdk = minSdkVersion
targetSdk = targetSdkVersion
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
testOptions.unitTests.isIncludeAndroidResources = true
}
dependencies {
implementation("com.google.firebase:firebase-common:21.0.0")
implementation("com.google.firebase:firebase-components:18.0.0")
}
Create src/main/AndroidManifest.xml
with the following content:
src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 Google LLC -->
<!-- -->
<!-- Licensed under the Apache License, Version 2.0 (the "License"); -->
<!-- you may not use this file except in compliance with the License. -->
<!-- You may obtain a copy of the License at -->
<!-- -->
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
<!-- -->
<!-- Unless required by applicable law or agreed to in writing, software -->
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
<!-- See the License for the specific language governing permissions and -->
<!-- limitations under the License. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<service android:name="com.google.firebase.components.ComponentDiscoveryService"
android:exported="false">
<meta-data
android:name="com.google.firebase.components:com.google.firebase.foo.FirebaseFooRegistrar"
android:value="com.google.firebase.components.ComponentRegistrar" />
</service>
</application>
</manifest>
Create com.google.firebase.foo.FirebaseFoo
For Kotlin
src/main/kotlin/com/google/firebase/foo/FirebaseFoo.kt
class FirebaseFoo {
companion object {
@JvmStatic
val instance: FirebaseFoo
get() = getInstance(Firebase.app)
@JvmStatic fun getInstance(app: FirebaseApp): FirebaseFoo = app.get(FirebaseFoo::class.java)
}
}
For Java
src/main/java/com/google/firebase/foo/FirebaseFoo.java
public class FirebaseFoo {
public static FirebaseFoo getInstance() {
return getInstance(FirebaseApp.getInstance());
}
public static FirebaseFoo getInstance(FirebaseApp app) {
return app.get(FirebaseFoo.class);
}
}
Create com.google.firebase.foo.FirebaseFooRegistrar
For Kotlin
src/main/kotlin/com/google/firebase/foo/FirebaseFooRegistrar.kt
You should strongly consider using Dependency Injection to instantiate your sdk instead of manually constructing its instance in the factory()
below.
class FirebaseFooRegistrar : ComponentRegistrar {
override fun getComponents() =
listOf(
Component.builder(FirebaseFoo::class.java).factory { container -> FirebaseFoo() }.build(),
LibraryVersionComponent.create("fire-foo", BuildConfig.VERSION_NAME)
)
}
For Java
src/main/java/com/google/firebase/foo/FirebaseFooRegistrar.java
public class FirebaseFooRegistrar implements ComponentRegistrar {
@Override
public List<Component<?>> getComponents() {
return Arrays.asList(
Component.builder(FirebaseFoo.class).factory(c -> new FirebaseFoo()).build(),
LibraryVersionComponent.create("fire-foo", BuildConfig.VERSION_NAME));
}
}
Continue to How Firebase works.