Gemini Live API

For applications that require real-time and low latency voice support, such as chatbots or agentic interactions, the Gemini Live API provides an optimized way to stream both input and output for a Gemini model. By using Firebase AI Logic, you can call the Gemini Live API directly from your Android app without the need for a backend integration. This guide shows you how to use the Gemini Live API in your Android app with Firebase AI Logic.

Get started

Before you begin, make sure your app targets API level 23 or higher.

If you haven't already, set up a Firebase project and connect your app to Firebase. For details, see the Firebase AI Logic documentation.

Set up your Android project

Add the Firebase AI Logic library and App Check dependencies to your app-level build.gradle.kts or build.gradle file. Use the Firebase Android BoM to manage library versions.

dependencies{
// Import the Firebase BoM
implementation(platform("com.google.firebase:firebase-bom:34.18.0"))
// Add the dependencies for the Firebase AI Logic and App Check libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation("com.google.firebase:firebase-ai")
implementation("com.google.firebase:firebase-appcheck-debug")
}

After adding the dependencies, sync your Android project with Gradle.

Configure the App Check debug provider for local development

Starting early July 2026, as part of the guided setup workflow for AI Logic in the Firebase console, Firebase App Check is automatically enforced to protect the Gemini API. For local development, you need to configure the App Check debug provider to bypass attestation while still maintaining the enforcement of App Check.

  1. In your debug build, configure App Check to use the debug provider factory:

    Kotlin

    Firebase.initialize(context=this)
    Firebase.appCheck.installAppCheckProviderFactory(
    DebugAppCheckProviderFactory.getInstance(),
    )
    

    Java

    FirebaseApp.initializeApp(/*context=*/this);
    FirebaseAppCheckfirebaseAppCheck=FirebaseAppCheck.getInstance();
    firebaseAppCheck.installAppCheckProviderFactory(
    DebugAppCheckProviderFactory.getInstance());
    
  2. Obtain your debug token:

    1. Run your app in the emulator or on your test device.

    2. Look for the App Check debug token in your logs. For example:

      D DebugAppCheckProvider: Enter this debug secret into the allow list
      in the Firebase Console for your project: 123a4567-b89c-12d3-e456-789012345678
      
    3. Copy the token (for example, 123a4567-b89c-12d3-e456-789012345678).

  3. Register your debug token with App Check:

    1. In the Firebase console, go to the Security > App Check > Apps tab.

    2. Find your app, click the overflow menu (), and then select Manage debug tokens.

    3. Follow the on-screen instructions to register your debug token.

For details about the debug provider (including how to get a new debug token), check out the official App Check docs.

Integrate Firebase AI Logic and initialize a generative model

Add the RECORD_AUDIO permission to the AndroidManifest.xml file of your application:

<uses-permissionandroid:name="android.permission.RECORD_AUDIO"/>

Initialize the Gemini Developer API backend service and access the LiveModel. Use a model that supports the Live API, like gemini-2.5-flash-native-audio-preview-12-2025. See the Firebase documentation for available Live API models.

To specify a voice, set the voice name within the speechConfig object as part of the model configuration. If you don't specify a voice, the default is Puck.

Kotlin

// Initialize the `LiveModel`
valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(
modelName="gemini-2.5-flash-native-audio-preview-12-2025",
generationConfig=liveGenerationConfig{
responseModality=ResponseModality.AUDIO
speechConfig=SpeechConfig(voice=Voice("FENRIR"))
}
)

Java

// Initialize the `LiveModel`
LiveGenerativeModelmodel=FirebaseAI
.getInstance(GenerativeBackend.googleAI())
.liveModel(
"gemini-2.5-flash-native-audio-preview-12-2025",
newLiveGenerationConfig.Builder()
.setResponseModality(ResponseModality.AUDIO)
.setSpeechConfig(newSpeechConfig(newVoice("FENRIR"))
).build(),
null,
null
);

You can optionally define a persona or role the model plays by setting a system instruction:

Kotlin

valsystemInstruction=content{
text("You are a helpful assistant, you main role is [...]")
}
valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(
modelName="gemini-2.5-flash-native-audio-preview-12-2025",
generationConfig=liveGenerationConfig{
responseModality=ResponseModality.AUDIO
speechConfig=SpeechConfig(voice=Voice("FENRIR"))
},
systemInstruction=systemInstruction,
)

Java

ContentsystemInstruction=newContent.Builder()
.addText("You are a helpful assistant, you main role is [...]")
.build();
LiveGenerativeModelmodel=FirebaseAI
.getInstance(GenerativeBackend.googleAI())
.liveModel(
"gemini-2.5-flash-native-audio-preview-12-2025",
newLiveGenerationConfig.Builder()
.setResponseModality(ResponseModality.AUDIO)
.setSpeechConfig(newSpeechConfig(newVoice("FENRIR"))
).build(),
tools,// null if you don't want to use function calling
systemInstruction
);

You can further specialize the conversation with the model by using system instructions to provide context specific to your app (for example, user in-app activity history).

Initialize a Live API session

Once you create the LiveModel instance, call model.connect() to create a LiveSession object and establish a persistent connection with the model with low-latency streaming. LiveSession lets you to interact with the model by starting and stopping the voice session and also sending and receiving text.

You can then call startAudioConversation() to start the conversation with the model:

Kotlin

valsession=model.connect()
session.startAudioConversation()

Java

LiveModelFuturesmodel=LiveModelFutures.from(liveModel);
ListenableFuture<LiveSession>sessionFuture=model.connect();
Futures.addCallback(sessionFuture,newFutureCallback<LiveSession>(){
@Override
publicvoidonSuccess(LiveSessionses){
LiveSessionFuturessession=LiveSessionFutures.from(ses);
session.startAudioConversation();
}
@Override
publicvoidonFailure(Throwablet){
// Handle exceptions
}
},executor);

In your conversations with the model, note that it doesn't handle interruptions. Also, the Live API is bidirectional so you use the same connection to send and receive content.

You can also use the Gemini Live API to generate audio from different input modalities:

Function calling: connect the Gemini Live API to your app

To go one step further, you can also enable the model to interact directly with the logic of your app using function calling.

Function calling (or tool calling) is a feature of generative AI implementations that allows the model to call functions at its own initiative to perform actions. If the function has an output, the model adds it to its context and uses it for subsequent generations.

Diagram illustrating how the Gemini Live API allows a user prompt to be interpreted by a model, triggering a predefined function with relevant arguments in an Android app, which then receives a confirmation response from the model.
Figure 1: Diagram illustrating how the Gemini Live API allows a user prompt to be interpreted by a model, triggering a predefined function with relevant arguments in an Android app, which then receives a confirmation response from the model.

To implement function calling in your app, start by creating a FunctionDeclaration object for each function you want to expose to the model.

For example, to expose an addList function that appends a string to a list of strings to Gemini, start by creating a FunctionDeclaration variable with a name and a short description in plain English of the function and its parameter:

Kotlin

valitemList=mutableListOf<String>()
funaddList(item:String){
itemList.add(item)
}
valaddListFunctionDeclaration=FunctionDeclaration(
name="addList",
description="Function adding an item the list",
parameters=mapOf(
"item"toSchema.string("A short string describing the item to add to the list")
)
)

Java

HashMap<String,Schema>addListParams=newHashMap<String,Schema>(1);
addListParams.put("item",Schema.str("A short string describing the item to add to the list"));
FunctionDeclarationaddListFunctionDeclaration=newFunctionDeclaration(
"addList",
"Function adding an item the list",
addListParams,
Collections.emptyList()
);

Then, pass this FunctionDeclaration as a Tool to the model when you instantiate it:

Kotlin

valaddListTool=Tool.functionDeclarations(listOf(addListFunctionDeclaration))
valmodel=Firebase.ai(backend=GenerativeBackend.googleAI()).liveModel(
modelName="gemini-2.5-flash-native-audio-preview-12-2025",
generationConfig=liveGenerationConfig{
responseModality=ResponseModality.AUDIO
speechConfig=SpeechConfig(voice=Voice("FENRIR"))
},
systemInstruction=systemInstruction,
tools=listOf(addListTool)
)

Java

LiveGenerativeModelmodel=FirebaseAI.getInstance(
GenerativeBackend.googleAI()).liveModel(
"gemini-2.5-flash-native-audio-preview-12-2025",
newLiveGenerationConfig.Builder()
.setResponseModalities(ResponseModality.AUDIO)
.setSpeechConfig(newSpeechConfig(newVoice("FENRIR")))
.build(),
List.of(Tool.functionDeclarations(List.of(addListFunctionDeclaration))),
null,
systemInstruction
);

Finally, implement a handler function to handle the tool call the model makes and pass it back the response. This handler function provided to the LiveSession when you call startAudioConversation, takes a FunctionCallPart parameter and returns FunctionResponsePart:

Kotlin

session.startAudioConversation(::functionCallHandler)
// ...
funfunctionCallHandler(functionCall:FunctionCallPart):FunctionResponsePart{
returnwhen(functionCall.name){
"addList"->{
// Extract function parameter from functionCallPart
valitemName=functionCall.args["item"]!!.jsonPrimitive.content
// Call function with parameter
addList(itemName)
// Confirm the function call to the model
valresponse=JsonObject(
mapOf(
"success"toJsonPrimitive(true),
"message"toJsonPrimitive("Item $itemName added to the todo list")
)
)
FunctionResponsePart(functionCall.name,response)
}
else->{
valresponse=JsonObject(
mapOf(
"error"toJsonPrimitive("Unknown function: ${functionCall.name}")
)
)
FunctionResponsePart(functionCall.name,response)
}
}
}

Java

Futures.addCallback(sessionFuture,newFutureCallback<LiveSessionFutures>(){
@RequiresPermission(Manifest.permission.RECORD_AUDIO)
@Override
@OptIn(markerClass=PublicPreviewAPI.class)
publicvoidonSuccess(LiveSessionFuturesses){
ses.startAudioConversation(::handleFunctionCallFuture);
}
@Override
publicvoidonFailure(Throwablet){
// Handle exceptions
}
},executor);
// ...
ListenableFuture<JsonObject>handleFunctionCallFuture=Futures.transform(response,result->{
for(FunctionCallPartfunctionCall:result.getFunctionCalls()){
if(functionCall.getName().equals("addList")){
Map<String,JsonElement>args=functionCall.getArgs();
Stringitem=
JsonElementKt.getContentOrNull(
JsonElementKt.getJsonPrimitive(
locationJsonObject.get("item")));
returnaddList(item);
}
}
returnnull;
},Executors.newSingleThreadExecutor());

Next steps

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2026年09月01日 UTC.