כדי לגשת למודלים Gemini Pro ו-Flash, מומלץ למפתחי Android להשתמש ב-Gemini Developer API באמצעות Firebase AI Logic. היא מאפשרת לכם להתחיל בלי להזין פרטי כרטיס אשראי, ומספקת רמה נדיבה של שימוש בחינם. אחרי שתאמתו את השילוב עם בסיס משתמשים קטן, תוכלו להרחיב את השימוש על ידי מעבר לתוכנית בתשלום.
תחילת העבודה
לפני שמתקשרים עם Gemini API ישירות מהאפליקציה, צריך לבצע כמה פעולות, כולל היכרות עם יצירת הנחיות והגדרת Firebase והאפליקציה לשימוש ב-SDK.
התנסות בהנחיות
ניסוי עם הנחיות יכול לעזור לכם למצוא את הניסוח, התוכן והפורמט הכי טובים לאפליקציית Android שלכם. Google AI Studio הוא סביבת פיתוח משולבת (IDE) שבה תוכלו ליצור אב טיפוס ולעצב הנחיות לתרחישי השימוש באפליקציה שלכם.
יצירת ההנחיה הנכונה לתרחיש השימוש שלכם היא יותר אומנות מאשר מדע, ולכן חשוב מאוד לבצע ניסויים. מידע נוסף על הנחיות זמין במסמכי Firebase.
אחרי שיוצרים את ההנחיה הרצויה, לוחצים על הלחצן "<>" כדי לקבל קטעי קוד שאפשר להוסיף לקוד.
הגדרת פרויקט Firebase וקישור האפליקציה ל-Firebase
כשמוכנים לקרוא ל-API מהאפליקציה, פועלים לפי ההוראות שבקטע 'שלב 1' במדריך לתחילת העבודה עם Firebase AI Logic כדי להגדיר את Firebase ואת ה-SDK באפליקציה.
הוספת יחסי התלות של Gradle
מוסיפים את יחסי התלות הבאים של Gradle למודול האפליקציה:
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")
}
הפעלת המודל הגנרטיבי
כדי להתחיל, יוצרים מופע של GenerativeModel
ומציינים את שם המודל:
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);
מידע נוסף על המודלים הזמינים לשימוש עם 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
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);
}
כדי לספק קובץ וידאו, ממשיכים להשתמש בסוג התוכן 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();
}
באופן דומה, אפשר גם להעביר מסמכי 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 = 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);
יצירת תמונות
מודל התמונות Gemini 2.5 Flash (שנקרא גם Nano Banana) יכול ליצור ולערוך תמונות על סמך ידע על העולם והסקת מסקנות. הוא יוצר תמונות שרלוונטיות להקשר, ומשלב בצורה חלקה בין טקסט ותמונות. הוא גם יכול ליצור תמונות מדויקות עם רצפים ארוכים של טקסט, והוא תומך בעריכת תמונות בשיחה תוך שמירה על ההקשר.
אפשר להשתמש במודלים של Imagen במקום ב-Gemini, במיוחד כדי ליצור תמונות באיכות גבוהה שדורשות ריאליזם פוטוגרפי, פרטים אומנותיים או סגנונות ספציפיים. עם זאת, ברוב תרחישי השימוש בצד הלקוח באפליקציות ל-Android, Gemini יספיק בהחלט.
במדריך הזה מוסבר איך להשתמש במודל Gemini 2.5 Flash Image באמצעות Firebase AI Logic SDK ל-Android. לפרטים נוספים על יצירת תמונות באמצעות Gemini, אפשר לעיין בתיעוד בנושא יצירת תמונות באמצעות Gemini ב-Firebase. אם אתם רוצים להשתמש במודלים של Imagen, כדאי לעיין במסמכים.

הפעלת המודל הגנרטיבי
מפעילים את GenerativeModel
ומציינים את שם המודל
gemini-2.5-flash-image-preview
. מוודאים שהגדרתם את responseModalities
כך שיכלול גם את TEXT
וגם את 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);
יצירת תמונות (קלט טקסט בלבד)
אתם יכולים לתת הנחיה למודל Gemini ליצור תמונות באמצעות הנחיה שמכילה רק טקסט:
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);
עריכת תמונות (הזנת טקסט ותמונות)
אתם יכולים לבקש ממודל Gemini לערוך תמונות קיימות על ידי ציון טקסט ותמונה אחת או יותר בהנחיה:
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);
שיפור ועריכה של תמונות באמצעות צ'אט עם כמה תגובות
כדי לערוך תמונות בשיחה, אפשר להשתמש בשיחה עם זיכרון. כך אפשר לשלוח בקשות המשך כדי לשפר את העריכות בלי לשלוח מחדש את התמונה המקורית.
קודם כל, מתחילים צ'אט עם startChat()
, ואפשר גם לספק היסטוריית הודעות. אחר כך משתמשים בלחצן sendMessage()
להודעות הבאות:
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);
שיטות מומלצות ומגבלות
- פורמט הפלט: התמונות נוצרות כקובצי PNG עם מימד מקסימלי של 1,024 פיקסלים.
- סוגי קלט: המודל לא תומך בקלט של אודיו או וידאו ליצירת תמונות.
- תמיכה בשפות: כדי לקבל את הביצועים הכי טובים, מומלץ להשתמש בשפות הבאות:
אנגלית (
en
), ספרדית מקסיקנית (es-mx
), יפנית (ja-jp
), סינית פשוטה (zh-cn
) והינדי (hi-in
). - בעיות ביצירה:
- יצירת התמונות לא תמיד מופעלת, ולפעמים התוצאה היא טקסט בלבד. נסו לבקש במפורש פלט של תמונות (למשל, "תצור תמונה", "תספק תמונות תוך כדי התהליך", "תעדכן את התמונה").
- יכול להיות שהמודל יפסיק ליצור באמצע. אפשר לנסות שוב או להזין הנחיה אחרת.
- יכול להיות שהמודל ייצור טקסט כתמונה. כדאי לנסות לבקש במפורש פלט טקסט (למשל, "צור טקסט נרטיבי עם איורים").
פרטים נוספים זמינים במאמרי העזרה של Firebase.
השלבים הבאים
- מומלץ לעיין באפליקציה לדוגמה של Firebase ל-Android ובקטלוג הדוגמאות של AI ל-Android ב-GitHub.
- הכנת האפליקציה להפקה, כולל הגדרה של Firebase App Check כדי להגן על Gemini API מפני ניצול לרעה על ידי לקוחות לא מורשים.
- מידע נוסף על Firebase AI Logic זמין במסמכי Firebase.