Android'de Firebase Auth ve Functions işlevlerini kullanarak Cloud Vision ile Önemli Noktaları Güvenli Bir Şekilde Tanıyın

Uygulamanızdan Google Cloud API çağırmak için bir ara uygulama oluşturmanız gerekir Yetkilendirme işleyen ve API anahtarları gibi gizli değerleri koruyan REST API. Daha sonra yapmanız gerekenler bu ara hizmetle kimlik doğrulaması yapmak ve bu hizmetle iletişim kurmak için mobil uygulamanızda kod yazmanızı öneririz.

Bu REST API'yi oluşturmanın bir yolu da Firebase Authentication and Functions'ı kullanmaktır. Bu da size yönetilen, sunucusuz bir ağ geçidi Kimlik doğrulama yapan ve mobil uygulamanızdan çağrılabilen Google Cloud API'leri SDK'ları kullanabilirsiniz.

Bu kılavuzda, Cloud Vision API'yi uygulamanızdan çağırmak için bu tekniğin nasıl kullanılacağı gösterilmektedir. Bu yöntem, kimliği doğrulanmış tüm kullanıcıların Cloud projeniz üzerinden Cloud Vision'da faturalandırılan hizmetlere erişmesine olanak tanır. Devam etmeden önce bu kimlik doğrulama mekanizmasının kullanım alanınız için yeterli olup olmadığını değerlendirin.

Başlamadan önce

Projenizi yapılandırın

  1. Henüz yapmadıysanız Firebase'i Android projenize ekleyin.
  2. Projeniz için Cloud tabanlı API'leri henüz etkinleştirmediyseniz etkinleştirin şimdi:

    1. Firebase ML Firebase konsolunun API'ler sayfası.
    2. Projenizi daha önce Blaze fiyatlandırma planına yükseltmediyseniz Bunun için yeni sürüme geçin. (Yalnızca emin olun.)

      Bulut tabanlı API'ler yalnızca Blaze düzeyindeki projelerde kullanılabilir.

    3. Cloud tabanlı API'ler henüz etkinleştirilmemişse Bulut tabanlı API'leri etkinleştir'i tıklayın. API'ler.
    ziyaret edin.
  3. Cloud'a erişimi engellemek için mevcut Firebase API anahtarlarınızı yapılandırın Vision API:
    1. Cloud Console'un Kimlik Bilgileri sayfasını açın.
    2. Listedeki her API anahtarı için düzenleme görünümünü açın ve Anahtar Kısıtlamalar bölümünde, Cloud Vision haricindeki tüm mevcut API'leri ekleyin. API'yi ekleyin.

Çağrılabilir işlevi dağıtma

Ardından, uygulamanız ile Cloud arasında köprü kurmak için kullanacağınız Cloud Functions işlevini dağıtın Vision API. functions-samples deposu, örnek içeriyor kullanabilirsiniz.

Varsayılan olarak, Cloud Vision API'ye bu işlev üzerinden erişmek yalnızca uygulamanızın kimliği doğrulanmış kullanıcılarının Cloud Vision API'ye erişmesini sağlayın. Şunları yapabilirsiniz: işlevi farklı gereksinimlere göre değiştirebilir.

İşlevi dağıtmak için:

  1. functions-samples deposunu klonlama veya indirme ve Node-1st-gen/vision-annotate-image dizinine geçiş yapın:
    git clone https://github.com/firebase/functions-samples
    cd Node-1st-gen/vision-annotate-image
    
  2. Bağımlılıkları yükleyin:
    cd functions
    npm install
    cd ..
  3. Firebase CLI'ınız yoksa yükleyin.
  4. vision-annotate-image içinde bir Firebase projesi başlatın dizin. İstendiğinde listeden projenizi seçin.
    firebase init
  5. İşlevi dağıtın:
    firebase deploy --only functions:annotateImage

Firebase Auth'u uygulamanıza ekleyin

Yukarıda dağıtılan çağrılabilir işlev, kimliği doğrulanmamıştan gelen tüm istekleri reddeder en iyi uygulamaları paylaşacağız. Henüz yapmadıysanız Firebase'i Uygulamanız için kimlik doğrulama.

Gerekli bağımlılıkları uygulamanıza ekleyin

  • Cloud Functions for Firebase (istemci) ve gson Android kitaplıklarına bağımlılıkları ekleyin. modül (uygulama düzeyinde) Gradle dosyanıza (genellikle <project>/<app-module>/build.gradle.kts veya <project>/<app-module>/build.gradle):
    implementation("com.google.firebase:firebase-functions:21.0.0")
    implementation("com.google.code.gson:gson:2.8.6")
  • 1. Giriş resmini hazırlama

    Cloud Vision'ı çağırmak için görüntünün base64 kodlu bir dize olarak biçimlendirilmelidir. Bir resim içeren bir resim dosyası olarak:
    1. Resmi Bitmap nesnesi olarak alın:

      Kotlin+KTX

      var bitmap: Bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri)

      Java

      Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
    2. Dilerseniz bant genişliğinden tasarruf etmek için resmin ölçeğini küçültebilirsiniz. Bkz. Cloud Vision'ın önerilen resim boyutları.

      Kotlin+KTX

      private fun scaleBitmapDown(bitmap: Bitmap, maxDimension: Int): Bitmap {
          val originalWidth = bitmap.width
          val originalHeight = bitmap.height
          var resizedWidth = maxDimension
          var resizedHeight = maxDimension
          if (originalHeight > originalWidth) {
              resizedHeight = maxDimension
              resizedWidth =
                  (resizedHeight * originalWidth.toFloat() / originalHeight.toFloat()).toInt()
          } else if (originalWidth > originalHeight) {
              resizedWidth = maxDimension
              resizedHeight =
                  (resizedWidth * originalHeight.toFloat() / originalWidth.toFloat()).toInt()
          } else if (originalHeight == originalWidth) {
              resizedHeight = maxDimension
              resizedWidth = maxDimension
          }
          return Bitmap.createScaledBitmap(bitmap, resizedWidth, resizedHeight, false)
      }

      Java

      private Bitmap scaleBitmapDown(Bitmap bitmap, int maxDimension) {
          int originalWidth = bitmap.getWidth();
          int originalHeight = bitmap.getHeight();
          int resizedWidth = maxDimension;
          int resizedHeight = maxDimension;
      
          if (originalHeight > originalWidth) {
              resizedHeight = maxDimension;
              resizedWidth = (int) (resizedHeight * (float) originalWidth / (float) originalHeight);
          } else if (originalWidth > originalHeight) {
              resizedWidth = maxDimension;
              resizedHeight = (int) (resizedWidth * (float) originalHeight / (float) originalWidth);
          } else if (originalHeight == originalWidth) {
              resizedHeight = maxDimension;
              resizedWidth = maxDimension;
          }
          return Bitmap.createScaledBitmap(bitmap, resizedWidth, resizedHeight, false);
      }

      Kotlin+KTX

      // Scale down bitmap size
      bitmap = scaleBitmapDown(bitmap, 640)

      Java

      // Scale down bitmap size
      bitmap = scaleBitmapDown(bitmap, 640);
    3. Bit eşlem nesnesini, base64 kodlamalı bir dizeye dönüştürün:

      Kotlin+KTX

      // Convert bitmap to base64 encoded string
      val byteArrayOutputStream = ByteArrayOutputStream()
      bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream)
      val imageBytes: ByteArray = byteArrayOutputStream.toByteArray()
      val base64encoded = Base64.encodeToString(imageBytes, Base64.NO_WRAP)

      Java

      // Convert bitmap to base64 encoded string
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
      bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
      byte[] imageBytes = byteArrayOutputStream.toByteArray();
      String base64encoded = Base64.encodeToString(imageBytes, Base64.NO_WRAP);
    4. Bitmap nesnesi tarafından temsil edilen resim, dik olmalıdır, ek döndürme gerekmez.

    2. Önemli noktaları tanımak için çağrılabilir işlevi çağırın

    Bir görüntüdeki önemli noktaları tanımak için çağrılabilir işlevi çağırın. JSON Cloud Vision isteği.

    1. Öncelikle, bir Cloud Functions örneğini başlatın:

      Kotlin+KTX

      private lateinit var functions: FirebaseFunctions
      // ...
      functions = Firebase.functions
      

      Java

      private FirebaseFunctions mFunctions;
      // ...
      mFunctions = FirebaseFunctions.getInstance();
      
    2. İşlevin çağrılması için bir yöntem tanımlayın:

      Kotlin+KTX

      private fun annotateImage(requestJson: String): Task<JsonElement> {
          return functions
              .getHttpsCallable("annotateImage")
              .call(requestJson)
              .continueWith { task ->
                  // This continuation runs on either success or failure, but if the task
                  // has failed then result will throw an Exception which will be
                  // propagated down.
                  val result = task.result?.data
                  JsonParser.parseString(Gson().toJson(result))
              }
      }
      

      Java

      private Task<JsonElement> annotateImage(String requestJson) {
          return mFunctions
                  .getHttpsCallable("annotateImage")
                  .call(requestJson)
                  .continueWith(new Continuation<HttpsCallableResult, JsonElement>() {
                      @Override
                      public JsonElement then(@NonNull Task<HttpsCallableResult> task) {
                          // This continuation runs on either success or failure, but if the task
                          // has failed then getResult() will throw an Exception which will be
                          // propagated down.
                          return JsonParser.parseString(new Gson().toJson(task.getResult().getData()));
                      }
                  });
      }
      
    3. Type ile bir JSON isteği oluşturma LANDMARK_DETECTION:

      Kotlin+KTX

      // Create json request to cloud vision
      val request = JsonObject()
      // Add image to request
      val image = JsonObject()
      image.add("content", JsonPrimitive(base64encoded))
      request.add("image", image)
      // Add features to the request
      val feature = JsonObject()
      feature.add("maxResults", JsonPrimitive(5))
      feature.add("type", JsonPrimitive("LANDMARK_DETECTION"))
      val features = JsonArray()
      features.add(feature)
      request.add("features", features)
      

      Java

      // Create json request to cloud vision
      JsonObject request = new JsonObject();
      // Add image to request
      JsonObject image = new JsonObject();
      image.add("content", new JsonPrimitive(base64encoded));
      request.add("image", image);
      //Add features to the request
      JsonObject feature = new JsonObject();
      feature.add("maxResults", new JsonPrimitive(5));
      feature.add("type", new JsonPrimitive("LANDMARK_DETECTION"));
      JsonArray features = new JsonArray();
      features.add(feature);
      request.add("features", features);
      
    4. Son olarak, işlevi çağırın:

      Kotlin+KTX

      annotateImage(request.toString())
          .addOnCompleteListener { task ->
              if (!task.isSuccessful) {
                  // Task failed with an exception
                  // ...
              } else {
                  // Task completed successfully
                  // ...
              }
          }
      

      Java

      annotateImage(request.toString())
              .addOnCompleteListener(new OnCompleteListener<JsonElement>() {
                  @Override
                  public void onComplete(@NonNull Task<JsonElement> task) {
                      if (!task.isSuccessful()) {
                          // Task failed with an exception
                          // ...
                      } else {
                          // Task completed successfully
                          // ...
                      }
                  }
              });
      

    3. Tanınan önemli noktalar hakkında bilgi alın

    Önemli nokta tanıma işlemi başarılı olursa, BatchAnnotateImagesResponse değeri, görevin sonucunda döndürülür. landmarkAnnotations içindeki her nesne dizisi, resimde tanınan bir belirgin noktayı temsil eder. Her önemli nokta için sınırlayıcı koordinatlarını giriş görüntüsünde görebilirsiniz. Yer işareti adı, enlem ve boylamını, Bilgi Grafiği varlık kimliğini (varsa) ve Maçın güven puanı. Örneğin:

    Kotlin+KTX

    for (label in task.result!!.asJsonArray[0].asJsonObject["landmarkAnnotations"].asJsonArray) {
        val labelObj = label.asJsonObject
        val landmarkName = labelObj["description"]
        val entityId = labelObj["mid"]
        val score = labelObj["score"]
        val bounds = labelObj["boundingPoly"]
        // Multiple locations are possible, e.g., the location of the depicted
        // landmark and the location the picture was taken.
        for (loc in labelObj["locations"].asJsonArray) {
            val latitude = loc.asJsonObject["latLng"].asJsonObject["latitude"]
            val longitude = loc.asJsonObject["latLng"].asJsonObject["longitude"]
        }
    }
    

    Java

    for (JsonElement label : task.getResult().getAsJsonArray().get(0).getAsJsonObject().get("landmarkAnnotations").getAsJsonArray()) {
        JsonObject labelObj = label.getAsJsonObject();
        String landmarkName = labelObj.get("description").getAsString();
        String entityId = labelObj.get("mid").getAsString();
        float score = labelObj.get("score").getAsFloat();
        JsonObject bounds = labelObj.get("boundingPoly").getAsJsonObject();
        // Multiple locations are possible, e.g., the location of the depicted
        // landmark and the location the picture was taken.
        for (JsonElement loc : labelObj.get("locations").getAsJsonArray()) {
            JsonObject latLng = loc.getAsJsonObject().get("latLng").getAsJsonObject();
            double latitude = latLng.get("latitude").getAsDouble();
            double longitude = latLng.get("longitude").getAsDouble();
        }
    }