Gemini Live API

chatbot やエージェント インタラクションなど、リアルタイムで低レイテンシの音声サポートが必要なアプリケーションの場合、Gemini Live API を使用すると、Gemini モデルの入力と出力の両方をストリーミングする最適化された方法が提供されます。Firebase AI Logic を使用すると、バックエンド統合を必要とせずに、Android アプリから Gemini Live API を直接呼び出すことができます。このガイドでは、Firebase AI Logic を使用して Android アプリで Gemini Live API を使用する方法について説明します。

始める

開始する前に、アプリが API レベル 23 以上を対象としていることを確認してください。

まだ設定していない場合は、Firebase プロジェクトを設定し、アプリを Firebase に接続します。詳細については、Firebase AI Logic のドキュメントをご覧ください。

Android プロジェクトを設定する

Firebase AI Logic ライブラリと App Check の依存関係をアプリレベルの build.gradle.kts ファイルまたは build.gradle ファイルに追加します。Firebase Android BoM を使用してライブラリのバージョンを管理します。

dependencies {
  // Import the Firebase BoM
  implementation(platform("com.google.firebase:firebase-bom:35.1.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")
}

依存関係を追加したら、Android プロジェクトを Gradle と同期します。

ローカル開発用に App Check デバッグ プロバイダを構成する

2026 年 7 月上旬より、Firebase コンソールの AI Logic のガイド付き設定ワークフローの一環として、Gemini API を保護するために Firebase App Check が自動的に適用されます。ローカル開発では、App Check の適用を維持しながら、App Check のデバッグ プロバイダを構成して、証明書をバイパスする必要があります。

  1. デバッグビルドで、デバッグ プロバイダ ファクトリを使用するように App Check を構成します。

    Kotlin

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

    Java

    FirebaseApp.initializeApp(/*context=*/ this);
    FirebaseAppCheck firebaseAppCheck = FirebaseAppCheck.getInstance();
    firebaseAppCheck.installAppCheckProviderFactory(
            DebugAppCheckProviderFactory.getInstance());
    
  2. デバッグ トークンを取得します。

    1. エミュレータまたはテストデバイスでアプリを実行します。

    2. ログで App Check デバッグ トークンを探します。次に例を示します。

      D DebugAppCheckProvider: Enter this debug secret into the allow list
      in the Firebase Console for your project: 123a4567-b89c-12d3-e456-789012345678
      
    3. トークン(例: 123a4567-b89c-12d3-e456-789012345678)をコピーします。

  3. App Check にデバッグ トークンを登録します。

    1. Firebase コンソールで、[セキュリティ] > [App Check] > [アプリ] タブに移動します。

    2. アプリを見つけて、オーバーフロー メニュー()をクリックし、[デバッグ トークンを管理] を選択します。

    3. 画面上の手順に沿ってデバッグ トークンを登録します。

デバッグ プロバイダの詳細(新しいデバッグ トークンの取得方法など)については、App Check の公式ドキュメントをご覧ください。

Firebase AI Logic を統合して生成モデルを初期化する

RECORD_AUDIO 権限をアプリの AndroidManifest.xml ファイルに追加します。

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

Gemini Developer API バックエンド サービスを初期化し、LiveModel にアクセスします。gemini-2.5-flash-native-audio-preview-12-2025 などの Live API をサポートするモデルを使用します。利用可能な Live API モデルについては、Firebase のドキュメントをご覧ください。

音声を指定するには、モデル構成の一部として、speechConfig オブジェクト内に音声名を設定します。音声を指定しない場合、デフォルトは Puck です。

Kotlin

// Initialize the `LiveModel`
val model = 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`
LiveGenerativeModel model = FirebaseAI
       .getInstance(GenerativeBackend.googleAI())
       .liveModel(
              "gemini-2.5-flash-native-audio-preview-12-2025",
              new LiveGenerationConfig.Builder()
                     .setResponseModality(ResponseModality.AUDIO)
                     .setSpeechConfig(new SpeechConfig(new Voice("FENRIR"))
              ).build(),
        null,
        null
);

必要に応じて、システム指示を設定して、モデルが果たすペルソナまたは役割を定義できます。

Kotlin

val systemInstruction = content {
    text("You are a helpful assistant, you main role is [...]")
}

val model = 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

Content systemInstruction = new Content.Builder()
       .addText("You are a helpful assistant, you main role is [...]")
       .build();

LiveGenerativeModel model = FirebaseAI
       .getInstance(GenerativeBackend.googleAI())
       .liveModel(
              "gemini-2.5-flash-native-audio-preview-12-2025",
              new LiveGenerationConfig.Builder()
                     .setResponseModality(ResponseModality.AUDIO)
                     .setSpeechConfig(new SpeechConfig(new Voice("FENRIR"))
              ).build(),
        tools, // null if you don't want to use function calling
        systemInstruction
);

システム指示を使用して、アプリに固有のコンテキスト(ユーザーのアプリ内アクティビティ履歴など)を提供することで、モデルとの会話をさらにカスタマイズできます。

Live API セッションを初期化する

LiveModel インスタンスを作成したら、model.connect() を呼び出して LiveSession オブジェクトを作成し、低レイテンシのストリーミ��グでモデルとの永続的な接続を確立します。LiveSession を使用すると、音声セッションの開始と停止、テキストの送受信を行うことで、モデルを操作できます。

その後、startAudioConversation() を呼び出してモデルとの会話を開始できます。

Kotlin

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

Java

LiveModelFutures model = LiveModelFutures.from(liveModel);
ListenableFuture<LiveSession> sessionFuture = model.connect();

Futures.addCallback(sessionFuture, new FutureCallback<LiveSession>() {
    @Override
    public void onSuccess(LiveSession ses) {
        LiveSessionFutures session = LiveSessionFutures.from(ses);
        session.startAudioConversation();
    }
    @Override
    public void onFailure(Throwable t) {
        // Handle exceptions
    }
}, executor);

モデルとの会話では、中断を処理しないことに注意してください。また、Live API は双方向であるため、同じ接続を使用してコンテンツを送受信します。

Gemini Live API を使用して、さまざまな入力モダリティから音声を生成することもできます。

関数呼び出し: Gemini Live API をアプリに接続する

さらに、関数呼び出しを使用して、モデルがアプリのロジックと直接やり取りできるようにすることもできます。

関数呼び出し(またはツー��呼び出し)��、生成 AI 実���の機能です。これにより、モデルは独自のイニシアチブで関数を呼び出してアクションを実行できます。関数に出力がある場合、モデルはそれをコンテキストに追加し、後続の生成に使用します。

Gemini Live API を使用して、ユーザー プロンプトをモデルで解釈し、Android アプリで関連する引数を使用して事前定義された関数をトリガーし、モデルから確認レスポンスを受け取る方法を示す図。
図 1: Gemini Live API がユーザー プロンプトをモデルで解釈し、Android アプリで関連する引数を使用して事前定義された関数をトリガーし、モデルから確認レスポンスを受け取る仕組みを示す図。

アプリに関数呼び出しを実装するには、まず、モデルに公開する関数ごとに FunctionDeclaration オブジェクトを作成します。

たとえば、文字列を文字列のリストに追加する addList 関数を Gemini に公開するには、まず、関数の名前と、関数とそのパラメータの簡単な説明をプレーンな英語で記述した FunctionDeclaration 変数を作成します。

Kotlin

val itemList = mutableListOf<String>()

fun addList(item: String) {
    itemList.add(item)
}

val addListFunctionDeclaration = FunctionDeclaration(
    name = "addList",
    description = "Function adding an item the list",
    parameters = mapOf(
        "item" to Schema.string("A short string describing the item to add to the list")
    )
)

Java

HashMap<String, Schema> addListParams = new HashMap<String, Schema>(1);

addListParams.put("item", Schema.str("A short string describing the item to add to the list"));

FunctionDeclaration addListFunctionDeclaration = new FunctionDeclaration(
    "addList",
    "Function adding an item the list",
    addListParams,
    Collections.emptyList()
);

次に、���の FunctionDeclaration を Tool としてモデルのインスタンス化時に渡します。

Kotlin

val addListTool = Tool.functionDeclarations(listOf(addListFunctionDeclaration))

val model = 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

LiveGenerativeModel model = FirebaseAI.getInstance(
    GenerativeBackend.googleAI()).liveModel(
        "gemini-2.5-flash-native-audio-preview-12-2025",
  new LiveGenerationConfig.Builder()
        .setResponseModality(ResponseModality.AUDIO)
        .setSpeechConfig(new SpeechConfig(new Voice("FENRIR")))
        .build(),
  List.of(Tool.functionDeclarations(List.of(addListFunctionDeclaration))),
               null,
               systemInstruction
        );

最後に、モデルが行うツール呼び出しを処理し、レスポンスを返すハンドラ関数を実装します。startAudioConversation を呼び出すときに LiveSession に提供されるこのハンドラ関数は、FunctionCallPart パラメータを受け取り、FunctionResponsePart を返します。

Kotlin

session.startAudioConversation(::functionCallHandler)

// ...

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

Java

Futures.addCallback(sessionFuture, new FutureCallback<LiveSessionFutures>() {

    @RequiresPermission(Manifest.permission.RECORD_AUDIO)
    @Override
    @OptIn(markerClass = PublicPreviewAPI.class)
    public void onSuccess(LiveSessionFutures ses) {
        ses.startAudioConversation(::handleFunctionCallFuture);
    }

    @Override
    public void onFailure(Throwable t) {
        // Handle exceptions
    }
}, executor);

// ...

ListenableFuture<JsonObject> handleFunctionCallFuture = Futures.transform(response, result -> {
    for (FunctionCallPart functionCall : result.getFunctionCalls()) {
        if (functionCall.getName().equals("addList")) {
            Map<String, JsonElement> args = functionCall.getArgs();
            String item =
                    JsonElementKt.getContentOrNull(
                            JsonElementKt.getJsonPrimitive(
                                    locationJsonObject.get("item")));
            return addList(item);
        }
    }
    return null;
}, Executors.newSingleThreadExecutor());

次のステップ