Gemini Developer API

借助 Gemini Developer API,您可以使用 Google 的 Gemini 模型,将尖端的生成式 AI 功能构建到 Android 应用中,包括对话式聊天、图片生成(使用 Nano Banana)以及根据文本、图片、音频和视频输入生成文本。

如需使用 Gemini Pro 和 Flash 模型,您可以使用 Gemini Developer API 和 Firebase AI Logic。这样,您无需提供信用卡即可开始使用,并且可以享受宽裕的免费层级。在您针对少量用户验证集成后,可以通过切换到付费层级进行扩容。

包含 Firebase Android SDK 的 Android 应用的图示。箭头从 SDK 指向云环境中的 Firebase。从 Firebase 出发,另一箭头指向 Gemini Developer API,后者与 Gemini Pro 和 Gemini Flash 相连,也位于 Cloud 中。
图 1. Firebase AI Logic 集成架构,用于访问 Gemini Developer API。

使用入门

在直接从应用与 Gemini API 交互之前,您需要先执行一些操作,包括熟悉提示以及设置 Firebase 和应用以使用 SDK。

实验提示

通过实验提示,您可以为 Android 应用找到最佳措辞、内容和 格式。Google AI Studio 是一种集成 开发环境 (IDE),您可以使用它为应用的使用场景设计提示原型 。

为您的使用场景创建有效的提示需要进行大量实验,这是该过程的关键部分。如需详细了解提示,请参阅 Firebase 文档

如果您对提示感到满意,请点击 <> 按钮以获取可添加到代码中的代码 段。

设置 Firebase 项目并将您的应用连接到 Firebase

准备好从应用调用 API 后,请按照 Firebase AI Logic 使用入门指南“第 1 步”中的说明设置 Firebase 并启用所需的 API 和服务。

添加 Gradle 依赖项

将以下 Gradle 依赖项添加到应用模块:

Kotlin

dependencies {
  // ... other androidx dependencies

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

Java

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

  // Required for one-shot operations (to use `ListenableFuture` from Guava Android)
  implementation("com.google.guava:guava:31.0.1-android")

  // Required for streaming operations (to use `Publisher` from Reactive Streams)
  implementation("org.reactivestreams:reactive-streams:1.0.4")
}

为本地开发配置 App Check 调试提供程序

从 2026 年 7 月初开始,在 Firebase 控制台中 AI Logic 的引导式设置工作流中,系统会自动强制执行 Firebase App Check 以保护 Gemini API。对于本地开发,您需要配置 App Check 调试提供程序,以绕过证明,同时仍保持 App Check 的强制执行。

  1. 在调试 build 中,将 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 文档

初始化生成模型

首先,实例化 GenerativeModel 并指定模型名称:

Kotlin

// Start by instantiating a GenerativeModel and specifying the model name:
val model = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel("gemini-2.5-flash")

Java

GenerativeModel firebaseAI = FirebaseAI.getInstance(GenerativeBackend.googleAI())
        .generativeModel("gemini-2.5-flash");

GenerativeModelFutures model = GenerativeModelFutures.from(firebaseAI);

详细了解可与 Gemini Developer API 搭配使用的可用模型。您还可以详细了解如何配置模型参数

从应用与 Gemini Developer API 交互

现在,您已设置 Firebase 和应用以使用 SDK,可以从应用与 Gemini Developer API 交互了。

生成文本

如需生成文本响应,请使用提示调用 generateContent()

Kotlin

scope.launch {
    val response = model.generateContent("Write a story about a magic backpack.")
}

Java

Content prompt = new Content.Builder()
        .addText("Write a story about a magic backpack.")
        .build();

ListenableFuture<GenerateContentResponse> response = model.generateContent(prompt);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

根据图片和其他媒体生成文本

您还可以根据包含文本以及图片或其他媒体的提示生成文本。调用 generateContent() 时,您可以将媒体作为内嵌数据传递。

例如,如需使用位图,请使用 image 内容类型:

Kotlin

scope.launch {
    val response = model.generateContent(
        content {
            image(bitmap)
            text("what is the object in the picture?")
        }
    )
}

Java

Content content = new Content.Builder()
        .addImage(bitmap)
        .addText("what is the object in the picture?")
        .build();

ListenableFuture<GenerateContentResponse> response = model.generateContent(content);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

如需传递音频文件,请使用 inlineData 内容类型:

Kotlin

scope.launch {
    val contentResolver = applicationContext.contentResolver
    contentResolver.openInputStream(audioUri).use { stream ->
        stream?.let {
            val bytes = it.readBytes()

            val prompt = content {
                inlineData(bytes, "audio/mpeg") // Specify the appropriate audio MIME type
                text("Transcribe this audio recording.")
            }

            val response = model.generateContent(prompt)
        }
    }
}

Java

ContentResolver resolver = applicationContext.getContentResolver();

try (InputStream stream = resolver.openInputStream(audioUri)) {
    File audioFile = new File(new URI(audioUri.toString()));
    int audioSize = (int) audioFile.length();
    byte[] audioBytes = new byte[audioSize];
    if (stream != null) {
        stream.read(audioBytes, 0, audioBytes.length);
        stream.close();

        // Provide a prompt that includes audio specified earlier and text
        Content prompt = new Content.Builder()
                .addInlineData(audioBytes, "audio/mpeg")  // Specify the appropriate audio MIME type
                .addText("Transcribe what's said in this audio recording.")
                .build();

        // To generate text output, call `generateContent` with the prompt
        ListenableFuture<GenerateContentResponse> response = model.generateContent(prompt);
        Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
            @Override
            public void onSuccess(GenerateContentResponse result) {
                String text = result.getText();
                Log.d(TAG, (text == null) ? "" : text);
            }
            @Override
            public void onFailure(Throwable t) {
                Log.e(TAG, "Failed to generate a response", t);
            }
        }, executor);
    } else {
        Log.e(TAG, "Error getting input stream for file.");
        // Handle the error appropriately
    }
} catch (IOException e) {
    Log.e(TAG, "Failed to read the audio file", e);
} catch (URISyntaxException e) {
    Log.e(TAG, "Invalid audio file", e);
}

如需提供视频文件,请继续使用 inlineData 内容类型:

Kotlin

scope.launch {
    val contentResolver = applicationContext.contentResolver
    contentResolver.openInputStream(videoUri).use { stream ->
        stream?.let {
            val bytes = it.readBytes()

            val prompt = content {
                inlineData(bytes, "video/mp4") // Specify the appropriate video MIME type
                text("Describe the content of this video")
            }

            val response = model.generateContent(prompt)
        }
    }
}

Java

ContentResolver resolver = applicationContext.getContentResolver();

try (InputStream stream = resolver.openInputStream(videoUri)) {
    File videoFile = new File(new URI(videoUri.toString()));
    int videoSize = (int) videoFile.length();
    byte[] videoBytes = new byte[videoSize];
    if (stream != null) {
        stream.read(videoBytes, 0, videoBytes.length);
        stream.close();

        // Provide a prompt that includes video specified earlier and text
        Content prompt = new Content.Builder()
                .addInlineData(videoBytes, "video/mp4")
                .addText("Describe the content of this video")
                .build();

        // To generate text output, call generateContent with the prompt
        ListenableFuture<GenerateContentResponse> response = model.generateContent(prompt);
        Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
            @Override
            public void onSuccess(GenerateContentResponse result) {
                String resultText = result.getText();
                System.out.println(resultText);
            }

            @Override
            public void onFailure(Throwable t) {
                t.printStackTrace();
            }
        }, executor);
    }
} catch (IOException e) {
    e.printStackTrace();
} catch (URISyntaxException e) {
    e.printStackTrace();
}

同样,您还可以通过将 PDF (application/pdf) 和纯文本 (text/plain) 文档各自的 MIME 类型作为参数传递,来传递这些文档。

多轮聊天

您还可以支持多轮对话。使用 startChat() 函数初始化聊天。您可以选择向模型提供消息历史记录。然后,调用 sendMessage() 函数以发送聊天消息。

Kotlin

val chat = model.startChat(
    history = listOf(
        content(role = "user") { text("Hello, I have 2 dogs in my house.") },
        content(role = "model") { text("Great to meet you. What would you like to know?") }
    )
)

scope.launch {
    val response = chat.sendMessage("How many paws are in my house?")
}

Java

Content.Builder userContentBuilder = new Content.Builder();
userContentBuilder.setRole("user");
userContentBuilder.addText("Hello, I have 2 dogs in my house.");
Content userContent = userContentBuilder.build();

Content.Builder modelContentBuilder = new Content.Builder();
modelContentBuilder.setRole("model");
modelContentBuilder.addText("Great to meet you. What would you like to know?");
Content modelContent = modelContentBuilder.build();

List<Content> history = Arrays.asList(userContent, modelContent);

// Initialize the chat
ChatFutures chat = model.startChat(history);

// Create a new user message
Content.Builder messageBuilder = new Content.Builder();
messageBuilder.setRole("user");
messageBuilder.addText("How many paws are in my house?");

Content message = messageBuilder.build();

// Send the message
ListenableFuture<GenerateContentResponse> response = chat.sendMessage(message);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        String resultText = result.getText();
        System.out.println(resultText);
    }

    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

在 Android 上使用 Nano Banana 生成图片

Gemini 2.5 Flash Image 模型(又称 Nano Banana)可以利用世界知识和推理能力生成和编辑图片。它可以生成与上下文相关的图片,无缝混合或交织文本和图片输出。它还可以使用长文本序列生成准确的视觉内容,并支持对话式图片编辑,同时保持上下文。

本指南介绍了如何使用适用于 Android 的 Firebase AI Logic SDK 使用 Gemini Image 模型(Nano Banana 模型)。如需详细了解如何使用 Gemini 生成图片,请参阅 Firebase 文档。

Google AI Studio 界面,显示一个文本输入框,其中包含提示“A hyper realistic picture of a t-rex with a blue bag pack roaming a pre-historic forest.”(一张超逼真的霸王龙图片,霸王龙背着蓝色背包在史前森林中漫步),以及一张生成的图片,其中显示一只背着蓝色背包的霸王龙在森林中漫步。
图 2. 使用 Google AI Studio 优化 Android
版 Nano Banana 图片生成提示

初始化生成模型

实例化 GenerativeModel 并指定模型名称 gemini-2.5-flash-image-preview。验证您是否配置了 responseModalities 以同时包含 TEXTIMAGE

Kotlin

val model = Firebase.ai(backend = GenerativeBackend.googleAI()).generativeModel(
    modelName = "gemini-2.5-flash-image-preview",
    // Configure the model to respond with text and images (required)
    generationConfig = generationConfig {
        responseModalities = listOf(
            ResponseModality.TEXT,
            ResponseModality.IMAGE
        )
    }
)

Java

GenerativeModel ai = FirebaseAI.getInstance(GenerativeBackend.googleAI()).generativeModel(
        "gemini-2.5-flash-image-preview",
        // Configure the model to respond with text and images (required)
        new GenerationConfig.Builder()
                .setResponseModalities(Arrays.asList(ResponseModality.TEXT, ResponseModality.IMAGE))
                .build()
);
GenerativeModelFutures model = GenerativeModelFutures.from(ai);

生成图片(仅限文本输入)

您可以仅提供文本提示,指示 Gemini 模型生成图片:

Kotlin

scope.launch {
    // Provide a text prompt instructing the model to generate an image
    val prompt =
        "A hyper realistic picture of a t-rex with a blue bag pack roaming a pre-historic forest."
    // To generate image output, call `generateContent` with the text input
    val generatedImageAsBitmap: Bitmap? = model.generateContent(prompt)
        .candidates.first().content.parts.filterIsInstance<ImagePart>()
        .firstOrNull()?.image
}

Java

// Provide a text prompt instructing the model to generate an image
Content prompt = new Content.Builder()
        .addText("Generate an image of the Eiffel Tower with fireworks in the background.")
        .build();
// To generate an image, call `generateContent` with the text input
ListenableFuture<GenerateContentResponse> response = model.generateContent(prompt);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        // iterate over all the parts in the first candidate in the result object
        for (Part part : result.getCandidates().get(0).getContent().getParts()) {
            if (part instanceof ImagePart) {
                ImagePart imagePart = (ImagePart) part;
                // The returned image as a bitmap
                Bitmap generatedImageAsBitmap = imagePart.getImage();
                break;
            }
        }
    }
    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

编辑图片(文本和图片输入)

您可以在提示中提供文本以及一张或多张图片,让 Gemini 模型编辑现有图片:

Kotlin

scope.launch {
    // Provide a text prompt instructing the model to edit the image
    val prompt = content {
        image(bitmap)
        text("Edit this image to make it look like a cartoon")
    }
    // To edit the image, call `generateContent` with the prompt (image and text input)
    val generatedImageAsBitmap: Bitmap? = model.generateContent(prompt)
        .candidates.first().content.parts.filterIsInstance<ImagePart>().firstOrNull()?.image
    // Handle the generated text and image
}

Java

// Provide an image for the model to edit
Bitmap bitmap = BitmapFactory.decodeResource(resources, R.drawable.scones);
// Provide a text prompt instructing the model to edit the image
Content promptcontent = new Content.Builder()
        .addImage(bitmap)
        .addText("Edit this image to make it look like a cartoon")
        .build();
// To edit the image, call `generateContent` with the prompt (image and text input)
ListenableFuture<GenerateContentResponse> response = model.generateContent(promptcontent);
Futures.addCallback(response, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        // iterate over all the parts in the first candidate in the result object
        for (Part part : result.getCandidates().get(0).getContent().getParts()) {
            if (part instanceof ImagePart) {
                ImagePart imagePart = (ImagePart) part;
                Bitmap generatedImageAsBitmap = imagePart.getImage();
                break;
            }
        }
    }
    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

通过多轮聊天迭代和编辑图片

如需采用对话式方法编辑图片,您可以使用多轮聊天。 这样,您无需重新发送原始图片,即可发出后续请求来优化编辑。

首先,使用 startChat() 初始化聊天,您可以选择提供消息历史记录。然后,对后续消息使用 sendMessage()

Kotlin

scope.launch {
    // Create the initial prompt instructing the model to edit the image
    val prompt = content {
        image(bitmap)
        text("Edit this image to make it look like a cartoon")
    }
    // Initialize the chat
    val chat = model.startChat()
    // To generate an initial response, send a user message with the image and text prompt
    var response = chat.sendMessage(prompt)
    // Inspect the returned image
    var generatedImageAsBitmap: Bitmap? = response
        .candidates.first().content.parts.filterIsInstance<ImagePart>().firstOrNull()?.image
    // Follow up requests do not need to specify the image again
    response = chat.sendMessage("But make it old-school line drawing style")
    generatedImageAsBitmap = response
        .candidates.first().content.parts.filterIsInstance<ImagePart>().firstOrNull()?.image
}

Java

// Provide an image for the model to edit
Bitmap bitmap = BitmapFactory.decodeResource(resources, R.drawable.scones);
// Initialize the chat
ChatFutures chat = model.startChat();
// Create the initial prompt instructing the model to edit the image
Content prompt = new Content.Builder()
        .setRole("user")
        .addImage(bitmap)
        .addText("Edit this image to make it look like a cartoon")
        .build();
// To generate an initial response, send a user message with the image and text prompt
ListenableFuture<GenerateContentResponse> response = chat.sendMessage(prompt);
// Extract the image from the initial response
ListenableFuture<Bitmap> initialRequest = Futures.transform(response,
        result -> {
            for (Part part : result.getCandidates().get(0).getContent().getParts()) {
                if (part instanceof ImagePart) {
                    ImagePart imagePart = (ImagePart) part;
                    return imagePart.getImage();
                }
            }
            return null;
        }, executor);
// Follow up requests do not need to specify the image again
ListenableFuture<GenerateContentResponse> modelResponseFuture = Futures.transformAsync(
        initialRequest,
        generatedImage -> {
            Content followUpPrompt = new Content.Builder()
                    .addText("But make it old-school line drawing style")
                    .build();
            return chat.sendMessage(followUpPrompt);
        }, executor);
// Add a final callback to check the reworked image
Futures.addCallback(modelResponseFuture, new FutureCallback<GenerateContentResponse>() {
    @Override
    public void onSuccess(GenerateContentResponse result) {
        for (Part part : result.getCandidates().get(0).getContent().getParts()) {
            if (part instanceof ImagePart) {
                ImagePart imagePart = (ImagePart) part;
                Bitmap generatedImageAsBitmap = imagePart.getImage();
                break;
            }
        }
    }
    @Override
    public void onFailure(Throwable t) {
        t.printStackTrace();
    }
}, executor);

注意事项和限制

请注意以下注意事项和限制:

  • 输出格式:图片以 PNG 格式生成,最大尺寸 为 1024 像素。
  • 输入类型:该模型不支持音频或视频输入来生成图片 。
  • 语言支持:为获得最佳性能,请使用以下语言: 英语 (en)、墨西哥西班牙语 (es-mx)、日语 (ja-jp)、简体 中文 (zh-cn) 和印地语 (hi-in)。
  • 生成问题
    • 图片生成可能不会始终触发,有时只会输出文本。尝试明确要求生成图片输出 (例如,“生成图片”“在您操作过程中提供图片”“更新图片”)。
    • 模型可能会中途停止生成。请重试或尝试其他提示
    • 模型可能会以图片形式生成文本。尝试明确要求文本输出 (例如,“生成叙事文本及插图”)。

如需了解详情,请参阅 Firebase 文档

后续步骤

设置应用后,请考虑以下后续步骤: