Para acceder a los modelos de Gemini Pro y Flash, recomendamos a los desarrolladores de Android que usen la API de Gemini Developer con Firebase AI Logic. Te permite comenzar sin necesidad de una tarjeta de crédito y ofrece un nivel gratuito generoso. Una vez que valides tu integración con una pequeña base de usuarios, puedes cambiar al nivel pagado para aumentar la escala.
Cómo comenzar
Antes de interactuar con la API de Gemini directamente desde tu app, primero deberás hacer algunas cosas, como familiarizarte con las instrucciones y configurar Firebase y tu app para usar el SDK.
Experimenta con instrucciones
Experimentar con instrucciones puede ayudarte a encontrar la mejor redacción, el mejor contenido y el mejor formato para tu app para Android. Google AI Studio es un IDE que puedes usar para crear prototipos y diseñar instrucciones para los casos de uso de tu app.
Crear la instrucción adecuada para tu caso de uso es más arte que ciencia, por lo que la experimentación es fundamental. Puedes obtener más información sobre las instrucciones en la documentación de Firebase.
Cuando estés conforme con tu instrucción, haz clic en el botón "<>" para obtener fragmentos de código que puedes agregar a tu código.
Configura un proyecto de Firebase y conecta tu app a Firebase
Cuando esté todo listo para llamar a la API desde tu app, sigue las instrucciones del "Paso 1" de la guía de introducción a Firebase AI Logic para configurar Firebase y el SDK en tu app.
Agrega la dependencia de Gradle
Agrega la siguiente dependencia de Gradle al módulo de tu app:
Kotlin
dependencies {
// ... other androidx dependencies
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:firebase-bom:34.2.0"))
// Add the dependency for the Firebase AI Logic library When using the BoM,
// you don't specify versions in Firebase library dependencies
implementation("com.google.firebase:firebase-ai")
}
Java
dependencies {
// Import the BoM for the Firebase platform
implementation(platform("com.google.firebase:34.2.0"))
// Add the dependency for the Firebase AI Logic library When using the BoM,
// you don't specify versions in Firebase library dependencies
implementation("com.google.firebase:firebase-ai")
// 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")
}
Inicializa el modelo generativo
Comienza por crear una instancia de GenerativeModel
y especificar el nombre del modelo:
Kotlin
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);
Obtén más información sobre los modelos disponibles para usar con la API de Gemini Developer. También puedes obtener más información para configurar los parámetros del modelo.
Interactúa con la API de Gemini Developer desde tu app
Ahora que configuraste Firebase y tu app para usar el SDK, puedes interactuar con la API de Gemini Developer desde tu app.
Generar texto
Para generar una respuesta de texto, llama a generateContent()
con tu instrucción.
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);
Genera texto a partir de imágenes y otro contenido multimedia
También puedes generar texto a partir de una instrucción que incluya texto, imágenes o algún otro contenido multimedia. Cuando llamas a generateContent()
, puedes pasar el contenido multimedia como datos intercalados.
Por ejemplo, para usar un mapa de bits, usa el tipo de contenido 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);
Para pasar un archivo de audio, usa el tipo de contenido inlineData
:
Kotlin
val contentResolver = applicationContext.contentResolver
val inputStream = contentResolver.openInputStream(audioUri).use { stream ->
stream?.let {
val bytes = stream.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 = getApplicationContext().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);
}
Para proporcionar un archivo de video, sigue usando el tipo de contenido inlineData
:
Kotlin
val contentResolver = applicationContext.contentResolver
contentResolver.openInputStream(videoUri).use { stream ->
stream?.let {
val bytes = stream.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 = getApplicationContext().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();
}
De manera similar, también puedes pasar documentos PDF (application/pdf
) y de texto sin formato (text/plain
) pasando su respectivo tipo de MIME como parámetro.
Chat de varios turnos
También puedes admitir conversaciones de varios turnos. Inicializa un chat con la función startChat()
. De manera opcional, puedes proporcionar al modelo un historial de mensajes. Luego, llama a la función sendMessage()
para enviar mensajes de chat.
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 = userContentBuilder.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);
Generar imagen
El modelo de Gemini 2.5 Flash Image (también conocido como Nano Banana) puede generar y editar imágenes aprovechando el conocimiento del mundo y el razonamiento. Genera imágenes pertinentes según el contexto y combina o intercala sin problemas las imágenes y el texto resultantes. También puede generar imágenes precisas con secuencias de texto largas y admite la edición de imágenes conversacionales sin perder el contexto.
Como alternativa a Gemini, puedes usar los modelos de Imagen, en especial para la generación de imágenes de alta calidad que requieren fotorrealismo, detalles artísticos o estilos específicos. Sin embargo, para la mayoría de los casos de uso del cliente en apps para Android, Gemini será más que suficiente.
En esta guía, se describe cómo usar el modelo de imagen Gemini 2.5 Flash con el SDK de Firebase AI Logic para Android. Para obtener más detalles sobre la generación de imágenes con Gemini, consulta la documentación de Genera imágenes con Gemini en Firebase. Si te interesa usar los modelos de Imagen, consulta la documentación.

Inicializa el modelo generativo
Crea una instancia de GenerativeModel
y especifica el nombre del modelo gemini-2.5-flash-image-preview
. Verifica que hayas configurado responseModalities
para que incluya TEXT
y IMAGE
.
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);
Genera imágenes (entrada de solo texto)
Puedes indicarle a un modelo de Gemini que genere imágenes proporcionando una instrucción solo de texto:
Kotlin
// 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 = 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);
Edita imágenes (entrada de texto y de imagen)
Puedes pedirle a un modelo de Gemini que edite imágenes existentes proporcionando texto y una o más imágenes en tu instrucción:
Kotlin
// Provide an image for the model to edit
val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.scones)
// 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 = 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);
Itera y edita imágenes a través de un chat de varios turnos
Para un enfoque conversacional de la edición de imágenes, puedes usar el chat de varios turnos. Esto permite que se realicen solicitudes de seguimiento para definir mejor las ediciones sin necesidad de volver a enviar la imagen original.
Primero, inicializa un chat con startChat()
y, de manera opcional, proporciona un historial de mensajes. Luego, usa sendMessage()
para los mensajes posteriores:
Kotlin
// Provide an image for the model to edit
val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.scones)
// 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 = 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<@Nullable 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);
Prácticas recomendadas y limitaciones
- Formato de salida: Las imágenes se generan como PNG con una dimensión máxima de 1,024 px.
- Tipos de entrada: El modelo no admite entradas de audio ni video para la generación de imágenes.
- Idiomas admitidos: Para obtener el mejor rendimiento, usa los siguientes idiomas: inglés (
en
), español (México;es-mx
), japonés (ja-jp
), chino simplificado (zh-cn
) y hindi (hi-in
). - Problemas de generación:
- Es posible que la generación de imágenes no siempre se active, lo que a veces genera resultados solo de texto. Intenta pedir resultados de imágenes de forma explícita (p.ej., "genera una imagen", "proporciona imágenes a medida que avanzas", "actualiza la imagen").
- Es posible que el modelo deje de generar contenido a mitad de la respuesta. Vuelve a intentarlo o usa otra instrucción.
- El modelo puede generar texto como una imagen. Intenta pedir resultados de texto de forma explícita (p.ej., "Genera texto narrativo junto con ilustraciones").
Consulta la documentación de Firebase para obtener más detalles.
Próximos pasos
- Revisa la app de muestra de inicio rápido de Firebase para Android y el catálogo de muestras de IA para Android en GitHub.
- Prepara tu app para la producción, lo que incluye configurar la Verificación de aplicaciones de Firebase para proteger la API de Gemini contra abusos de clientes no autorizados.
- Obtén más información sobre Firebase AI Logic en la documentación de Firebase.