Firebase Data Connect client SDKs let you call your server-side queries and mutations directly from a Firebase app. You generate a custom client SDK in parallel as you design the schemas, queries and mutations you deploy to your Data Connect service. Then, you integrate methods from this SDK into your client logic.
As we've mentioned elsewhere, it's important to note that Data Connect queries and mutations are not submitted by client code and executed on the server. Instead, when deployed, Data Connect operations are stored on the server like Cloud Functions. This means you need to deploy corresponding client-side changes to avoid breaking existing users (for example, on older app versions).
That's why Data Connect provides you with a developer environment and tooling that lets you prototype your server-deployed schemas, queries and mutations. It also generates client-side SDKs automatically, while you prototype.
When you've iterated updates to your service and client apps, both server- and client-side updates are ready to deploy.
What is the client development workflow?
If you followed the Get started , you were introduced to the overall development flow for Data Connect . In this guide, you'll find more detailed information about generating Android SDKs from your schema and working with client queries and mutations.
To summarize, to use generated Android SDKs in your client apps, you'll follow these prerequisite steps:
- Add Firebase to your Android app.
- Configure Data Connect as a dependency in Gradle.
- Add the Kotlin Serialization Gradle plugin and Gradle dependency.
Then:
- Develop your app schema.
-  Set up SDK generation: - With the Add SDK to appbutton in our Data Connect VS Code extension
- By updating your connector.yaml
 
-  Set up and use the Data Connect emulator and iterate. 
Generate your Kotlin SDK
Use the Firebase 
CLI to set up Data Connect 
generated SDKs in your apps.
The init 
command should detect all apps in the current folder and install
generated SDKs automatically.
 firebase init dataconnect:sdk 
 
Update SDKs while prototyping
If you have Data Connect VS Code extension installed, it will always keep generated SDKs up to date.
If you don't use Data Connect VS Code extension, you can use Firebase CLI to keep generated SDKs up to date.
 firebase  
dataconnect:sdk:generate  
--watch 
 
Generate SDKs in build pipelines
You can use the Firebase CLI to generate Data Connect SDKs in CI/CD build processes.
 firebase  
dataconnect:sdk:generate 
 
Set up client code
Incorporate Data Connect into your client code
To set up your client code to use Data Connect and your generated SDK, first follow the standard Firebase setup instructions .
Then, add the following into the plugins 
section in app/build.gradle.kts 
:
  // The Firebase team tests with version 1.8.22; however, other 1.8 versions, 
 // and all newer versions are expected work too. 
 kotlin 
 ( 
 "plugin.serialization" 
 ) 
  
 version 
  
 "1.8.22" 
  
 // MUST match the version of the Kotlin compiler 
 
 
Then, add the following into the dependencies 
section in app/build.gradle.kts 
:
  implementation 
 ( 
 platform 
 ( 
 "com.google.firebase:firebase-bom:34.4.0" 
 )) 
 implementation 
 ( 
 "com.google.firebase:firebase-dataconnect" 
 ) 
 implementation 
 ( 
 "com.google.firebase:firebase-auth" 
 ) 
  
 // Optional 
 implementation 
 ( 
 "com.google.firebase:firebase-appcheck" 
 ) 
  
 // Optional 
 implementation 
 ( 
 "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3" 
 ) 
  
 // Newer versions should work too 
 implementation 
 ( 
 "org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1" 
 ) 
  
 // Newer versions should work too 
 
 
Initialize the Data Connect Android SDK
Initialize your Data Connect instance using the information you used to set up Data Connect (all available in the Firebase console Data Connect tab).
The ConnectorConfig object
The SDK requires a connector configuration object.
This object is automatically generated from serviceId 
and location 
in dataconnect.yaml 
, and connectorId 
in connector.yaml 
.
Getting a connector instance
Now that you've set up a configuration object, get a Data Connect 
connector instance. The code for your connector will be generated by the Data Connect 
emulator. If your connector name is movies 
and the
Kotlin package is com.myapplication 
, as specified in connector.yaml 
, then
retrieve the connector object by calling:
  val 
  
 connector 
  
 = 
  
 com 
 . 
 myapplication 
 . 
 MoviesConnector 
 . 
 instance 
 
 
Use queries and mutations from your Android SDK
With the connector object, you can run queries and mutations as defined in the GraphQL source code. Suppose your connector has these operations defined:
  mutation 
  
 createMovie 
 ( 
 $ 
 title 
 : 
  
 String 
 ! 
 , 
  
 $ 
 releaseYear 
 : 
  
 Int 
 ! 
 , 
  
 $ 
 genre 
 : 
  
 String 
 ! 
 , 
  
 $ 
 rating 
 : 
  
 Int 
 ! 
 ) 
  
 { 
  
 movie_insert 
 ( 
 data 
 : 
  
 { 
  
 title 
 : 
  
 $ 
 title 
  
 releaseYear 
 : 
  
 $ 
 releaseYear 
  
 genre 
 : 
  
 $ 
 genre 
  
 rating 
 : 
  
 $ 
 rating 
  
 }) 
 } 
 query 
  
 getMovieByKey 
 ( 
 $ 
 key 
 : 
  
 Movie_Key 
 ! 
 ) 
  
 { 
  
 movie 
 ( 
 key 
 : 
  
 $ 
 key 
 ) 
  
 { 
  
 id 
  
 title 
  
 } 
 } 
 query 
  
 listMoviesByGenre 
 ( 
 $ 
 genre 
 : 
  
 String 
 ! 
 ) 
  
 { 
  
 movies 
 ( 
 where 
 : 
  
 { 
 genre 
 : 
  
 { 
 eq 
 : 
  
 $ 
 genre 
 }}) 
  
 { 
  
 id 
  
 title 
  
 } 
 } 
 
 
then you could create and retrieve a movie as follows:
  val 
  
 connector 
  
 = 
  
 MoviesConnector 
 . 
 instance 
 val 
  
 addMovieResult1 
  
 = 
  
 connector 
 . 
 createMovie 
 . 
 execute 
 ( 
  
 title 
  
 = 
  
 "Empire Strikes Back" 
 , 
  
 releaseYear 
  
 = 
  
 1980 
 , 
  
 genre 
  
 = 
  
 "Sci-Fi" 
 , 
  
 rating 
  
 = 
  
 5 
 ) 
 val 
  
 movie1 
  
 = 
  
 connector 
 . 
 getMovieByKey 
 . 
 execute 
 ( 
 addMovieResult1 
 . 
 data 
 . 
 key 
 ) 
 println 
 ( 
 "Empire Strikes Back: 
 ${ 
 movie1 
 . 
 data 
 . 
 movie 
 } 
 " 
 ) 
 
 
You can also retrieve multiple movies:
  val 
  
 connector 
  
 = 
  
 MoviesConnector 
 . 
 instance 
 val 
  
 addMovieResult2 
  
 = 
  
 connector 
 . 
 createMovie 
 . 
 execute 
 ( 
  
 title 
 = 
 "Attack of the Clones" 
 , 
  
 releaseYear 
  
 = 
  
 2002 
 , 
  
 genre 
  
 = 
  
 "Sci-Fi" 
 , 
  
 rating 
  
 = 
  
 5 
 ) 
 val 
  
 listMoviesResult 
  
 = 
  
 connector 
 . 
 listMoviesByGenre 
 . 
 execute 
 ( 
 genre 
  
 = 
  
 "Sci-Fi" 
 ) 
 println 
 ( 
 listMoviesResult 
 . 
 data 
 . 
 movies 
 ) 
 
 
You can also collect a Flow 
that will only produce a result when a new query
result is retrieved using a call to the query's execute() 
method.
  val 
  
 connector 
  
 = 
  
 MoviesConnector 
 . 
 instance 
 connector 
 . 
 listMoviesByGenre 
 . 
 flow 
 ( 
 genre 
  
 = 
  
 "Sci-Fi" 
 ). 
 collect 
  
 { 
  
 data 
  
 - 
>  
 println 
 ( 
 data 
 . 
 movies 
 ) 
 } 
 connector 
 . 
 createMovie 
 . 
 execute 
 ( 
  
 title 
 = 
 "A New Hope" 
 , 
  
 releaseYear 
  
 = 
  
 1977 
 , 
  
 genre 
  
 = 
  
 "Sci-Fi" 
 , 
  
 rating 
  
 = 
  
 5 
 ) 
 connector 
 . 
 listMoviesByGenre 
 . 
 execute 
 ( 
 genre 
  
 = 
  
 "Sci-Fi" 
 ) 
  
 // will cause the Flow to get notified 
 
 
Handle changes to enumeration fields
An app's schema can contain enumerations , which can be accessed by your GraphQL queries .
As an app's design changes, you may add new enum supported values. For example,
imagine that later in your application’s lifecycle you decide to add a
FULLSCREEN value to the AspectRatio 
enum.
In the Data Connect workflow, you can use local development tooling to update your queries and SDKs.
However, before you release an updated version of your clients, older deployed clients may break.
Example resilient implementation
The generated SDK forces handling of unknown values as the customer's code must
unwrap the EnumValue 
object, which is either EnumValue.Known 
for known enum
values or EnumValue.Unknown 
for unknown values.
  val 
  
 result 
  
 = 
  
 connector 
 . 
 listMoviesByAspectRatio 
 . 
 execute 
 ( 
 AspectRatio 
 . 
 WIDESCREEN 
 ) 
 val 
  
 encounteredAspectRatios 
  
 = 
  
 mutableSetOf<String> 
 () 
 result 
 . 
 data 
 . 
 movies 
  
 . 
 mapNotNull 
  
 { 
  
 it 
 . 
 otherAspectRatios 
  
 } 
  
 . 
 forEach 
  
 { 
  
 otherAspectRatios 
  
 - 
>  
 otherAspectRatios 
  
 . 
 filterNot 
  
 { 
  
 it 
 . 
 value 
  
 == 
  
 AspectRatio 
 . 
 WIDESCREEN 
  
 } 
  
 . 
 forEach 
  
 { 
  
 when 
  
 ( 
 it 
 ) 
  
 { 
  
 is 
  
 EnumValue 
 . 
 Known 
  
 - 
>  
 encounteredAspectRatios 
 . 
 add 
 ( 
 it 
 . 
 value 
 . 
 name 
 ) 
  
 is 
  
 EnumValue 
 . 
 Unknown 
  
 - 
>  
 encounteredAspectRatios 
 . 
 add 
 ( 
 "[unknown ratio: 
 ${ 
 it 
 . 
 stringValue 
 } 
 ]" 
 ) 
  
 } 
  
 } 
  
 } 
 println 
 ( 
  
 "Widescreen movies also include additional aspect ratios: " 
  
 + 
  
 encounteredAspectRatios 
 . 
 sorted 
 (). 
 joinToString 
 () 
 ) 
 
 
Prototype and test your Android application
Instrument clients to use a local emulator
You can use the Data Connect emulator, whether from the Data Connect VS Code extension or from the CLI.
Instrumenting the app to connect to the emulator is the same for both scenarios.
  val 
  
 connector 
  
 = 
  
 MoviesConnector 
 . 
 instance 
 // Connect to the emulator on "10.0.2.2:9399" 
 connector 
 . 
 dataConnect 
 . 
 useEmulator 
 () 
 // (alternatively) if you're running your emulator on non-default port: 
 connector 
 . 
 dataConnect 
 . 
 useEmulator 
 ( 
 port 
  
 = 
  
 9999 
 ) 
 // Make calls from your app 
 
 
To switch to production resources, comment out lines for connecting to the emulator.
Data types in Data Connect SDKs
The Data Connect server represents common and custom GraphQL data types. These are represented in the SDK as follows.
| Data Connect Type | Kotlin | 
|---|---|
| String | String | 
| Int | Int (32-bit integer) | 
| Float | Double (64-bit float) | 
| Boolean | Boolean | 
| UUID | java.util.UUID | 
| Date | com.google.firebase.dataconnect.LocalDate (was java.util.Date until 16.0.0-beta03) | 
| Timestamp | com.google.firebase.Timestamp | 
| Int64 | Long | 
| Any | com.google.firebase.dataconnect.AnyValue | 

