כדי לקרוא ל-Cloud APIs מהאפליקציה, צריך ליצור API בארכיטקטורת REST ביניים שמטפל בהרשאות ומגן על ערכים סודיים כמו מפתחות API. לאחר מכן צריך לכתוב קוד באפליקציה לנייד כדי לבצע אימות ולתקשר עם שירות הביניים הזה.
אחת הדרכים ליצור את REST API היא באמצעות Firebase Authentication ו-Functions. כך מקבלים שער מנוהל ללא שרת (serverless) ל-Google Cloud APIs שמטפל באימות, ואפשר להפעיל אותו מהאפליקציה לנייד באמצעות ערכות SDK מוכנות מראש.
במדריך הזה מוסבר איך להשתמש בשיטה הזו כדי לבצע קריאה ל-Cloud Vision API מהאפליקציה שלכם. השיטה הזו מאפשרת לכל המשתמשים המאומתים לגשת לשירותים בתשלום של Cloud Vision דרך פרויקט בענן שלכם, לכן כדאי לשקול אם מנגנון ההרשאה הזה מספיק לתרחיש השימוש שלכם לפני שממשיכים.
לפני שמתחילים
הגדרת הפרויקט
אם עדיין לא הוספתם את Firebase לאפליקציה, אתם צריכים לעשות זאת לפי השלבים שמפורטים במדריך לתחילת העבודה.משתמשים ב-Swift Package Manager כדי להתקין ולנהל יחסי תלות ב-Firebase.
- ב-Xcode, כשפרויקט האפליקציה פתוח, עוברים אל File > Add Packages (קובץ > הוספת חבילות).
- כשמוצגת בקשה, מוסיפים את מאגר Firebase Apple platforms SDK:
- בוחרים בספרייה Firebase ML.
- מוסיפים את הדגל
-ObjCלקטע Other Linker Flags בהגדרות הבנייה של יעד הקישור. - אחרי שתסיימו, פלטפורמת Xcode תתחיל לטפל ביחסי התלות ולהוריד אותם ברקע באופן אוטומטי.
https://github.com/firebase/firebase-ios-sdk.git
עכשיו מבצעים הגדרה באפליקציה:
- באפליקציה, מייבאים את Firebase:
Swift
import FirebaseMLModelDownloader
Objective-C
@import FirebaseMLModelDownloader;
עוד כמה שלבי הגדרה, והכול יהיה מוכן:
-
אם עדיין לא הפעלתם ממשקי API מבוססי-Cloud בפרויקט, עכשיו הזמן לעשות זאת:
- פותחים את הדף Firebase ML APIs במסוף Firebase.
-
אם עדיין לא שדרגתם את הפרויקט לתוכנית התמחור Blaze בתשלום לפי שימוש, אתם צריכים ללחוץ על שדרוג. (תתבקשו לשדרג רק אם הפרויקט שלכם לא נמצא בתוכנית התמחור Blaze).
רק בפרויקטים עם מינוי Blaze בתשלום לפי שימוש אפשר להשתמש בממשקי API מבוססי-Cloud.
- אם ממשקי API מבוססי-ענן לא מופעלים כבר, לוחצים על הפעלת ממשקי API מבוססי-ענן.
- מגדירים את מפתחות ה-API הקיימים ב-Firebase כך שלא תהיה להם גישה ל-Cloud Vision API:
- פותחים את הדף Credentials במסוף Cloud.
- לכל מפתח API ברשימה, פותחים את תצוגת העריכה, ובקטע Key Restrictions מוסיפים לרשימה את כל ממשקי ה-API הזמינים חוץ מ-Cloud Vision API.
פריסת הפונקציה שאפשר לקרוא לה
בשלב הבא, פורסים את פונקציית Cloud Functions שבה ישתמשו כדי לגשר בין האפליקציה לבין Cloud Vision API. מאגר functions-samples מכיל דוגמה שאפשר להשתמש בה.
כברירת מחדל, גישה ל-Cloud Vision API דרך הפונקציה הזו תאפשר רק למשתמשים מאומתים של האפליקציה שלכם לגשת ל-Cloud Vision API. אפשר לשנות את הפונקציה בהתאם לדרישות שונות.
כדי לפרוס את הפונקציה:
- משכפלים או מורידים את המאגר functions-samples
ועוברים לספרייה
Node-1st-gen/vision-annotate-image:git clone https://github.com/firebase/functions-samplescd Node-1st-gen/vision-annotate-image - יחסי תלות של התקנות:
cd functionsnpm installcd .. - אם לא מותקן Firebase CLI, מתקינים אותו.
- מאתחלים פרויקט Firebase בספרייה
vision-annotate-image. כשמופיעה בקשה, בוחרים את הפרויקט מהרשימה.firebase init
- פורסים את הפונקציה:
firebase deploy --only functions:annotateImage
הוספת Firebase Auth לאפליקציה
הפונקציה שאפשר להפעיל שהוצגה למעלה תדחה כל בקשה ממשתמשים לא מאומתים באפליקציה. אם עדיין לא עשיתם זאת, תצטרכו להוסיף את Firebase Auth לאפליקציה.
הוספת יחסי תלות נדרשים לאפליקציה
משתמשים ב-Swift Package Manager כדי להתקין את ספריית Cloud Functions for Firebase.
1. הכנת תמונת הקלט
כדי להתקשר אל Cloud Vision, התמונה צריכה להיות בפורמט של מחרוזת בקידוד Base64. כדי לעבדUIImage:
Swift
guard let imageData = uiImage.jpegData(compressionQuality: 1.0) else { return } let base64encodedImage = imageData.base64EncodedString()
Objective-C
NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f); NSString *base64encodedImage = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
2. הפעלת הפונקציה שאפשר לקרוא לה כדי לזהות ציוני דרך
כדי לזהות ציוני דרך בתמונה, מפעילים את הפונקציה שאפשר לקרוא לה ומעבירים בקשת JSON Cloud Vision.קודם, מאתחלים מופע של Cloud Functions:
Swift
lazy var functions = Functions.functions()Objective-C
@property(strong, nonatomic) FIRFunctions *functions;יוצרים בקשה עם סוג שמוגדר ל
LANDMARK_DETECTION:Swift
let requestData = [ "image": ["content": base64encodedImage], "features": ["maxResults": 5, "type": "LANDMARK_DETECTION"] ]Objective-C
NSDictionary *requestData = @{ @"image": @{@"content": base64encodedImage}, @"features": @{@"maxResults": @5, @"type": @"LANDMARK_DETECTION"} };לבסוף, מפעילים את הפונקציה:
Swift
do { let result = try await functions.httpsCallable("annotateImage").call(requestData) print(result) } catch { if let error = error as NSError? { if error.domain == FunctionsErrorDomain { let code = FunctionsErrorCode(rawValue: error.code) let message = error.localizedDescription let details = error.userInfo[FunctionsErrorDetailsKey] } // ... } }Objective-C
[[_functions HTTPSCallableWithName:@"annotateImage"] callWithObject:requestData completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) { if (error) { if ([error.domain isEqualToString:@"com.firebase.functions"]) { FIRFunctionsErrorCode code = error.code; NSString *message = error.localizedDescription; NSObject *details = error.userInfo[@"details"]; } // ... } // Function completed succesfully // Get information about labeled objects }];
3. קבלת מידע על ציוני הדרך שזוהו
אם פעולת הזיהוי של נקודת הציון תצליח, תוחזר תוצאה של המשימה בתגובת JSON של BatchAnnotateImagesResponse. כל אובייקט במערך landmarkAnnotations מייצג ציון דרך שזוהה בתמונה. לכל נקודת ציון, אפשר לקבל את קואורדינטות התיחום שלה בתמונת הקלט, את השם של נקודת הציון, את קווי הרוחב והאורך שלה, את מזהה הישות שלה בתרשים הידע (אם זמין) ואת ציון מהימנות ההתאמה. לדוגמה:
Swift
if let labelArray = (result?.data as? [String: Any])?["landmarkAnnotations"] as? [[String:Any]] {
for labelObj in labelArray {
let landmarkName = labelObj["description"]
let entityId = labelObj["mid"]
let score = labelObj["score"]
let bounds = labelObj["boundingPoly"]
// Multiple locations are possible, e.g., the location of the depicted
// landmark and the location the picture was taken.
guard let locations = labelObj["locations"] as? [[String: [String: Any]]] else { continue }
for location in locations {
let latitude = location["latLng"]?["latitude"]
let longitude = location["latLng"]?["longitude"]
}
}
}
Objective-C
NSArray *labelArray = result.data[@"landmarkAnnotations"];
for (NSDictionary *labelObj in labelArray) {
NSString *landmarkName = labelObj[@"description"];
NSString *entityId = labelObj[@"mid"];
NSNumber *score = labelObj[@"score"];
NSArray *bounds = labelObj[@"boundingPoly"];
// Multiple locations are possible, e.g., the location of the depicted
// landmark and the location the picture was taken.
NSArray *locations = labelObj[@"locations"];
for (NSDictionary *location in locations) {
NSNumber *latitude = location[@"latLng"][@"latitude"];
NSNumber *longitude = location[@"latLng"][@"longitude"];
}
}