Chamar o back-end da Pesquisa de produtos da API Vision no Android

1. Antes de começar

bd8c01b2f8013c6d.png

Você já viu a demonstração do Google Lens, em que é possível apontar a câmera do smartphone para um objeto e encontrar onde comprar on-line? Se você quiser aprender a adicionar o mesmo recurso ao seu app, este codelab é para você. Ele faz parte de um programa de aprendizado que ensina a criar um recurso de pesquisa de imagem de produto em um app para dispositivos móveis.

Neste codelab, você vai aprender a chamar um back-end criado com a Pesquisa de produtos da API Vision em um app para dispositivos móveis. Esse back-end pode usar uma imagem de consulta e pesquisar produtos visualmente semelhantes em um catálogo.

Saiba mais sobre as etapas restantes da criação de um recurso de pesquisa visual de produtos, incluindo como usar a detecção e rastreamento de objetos do ML Kit para detectar objetos na imagem de consulta e permitir que os usuários escolham qual produto pesquisar, no programa de aprendizado.

O que você vai criar

  • Neste codelab, você vai começar com o app Android que pode detectar objetos de uma imagem de entrada. Você vai escrever um código para pegar o objeto escolhido pelo usuário, enviá-lo ao back-end da pesquisa de produtos e mostrar o resultado na tela.
  • No final, você vai ver algo parecido com a imagem à direita.

O que você vai aprender

  • Como chamar e analisar a resposta das APIs da Pesquisa de produtos da API Vision em um app Android

O que é necessário

  • Uma versão recente do Android Studio (v4.1.2 ou mais recente)
  • Emulador do Android Studio ou um dispositivo Android físico
  • Código de amostra
  • Conhecimento básico de desenvolvimento para Android em Kotlin.

Este codelab é focado na Pesquisa de produtos da API Vision. Conceitos não relevantes e blocos de código não são abordados e são fornecidos para que você simplesmente os copie e cole.

2. Sobre a Pesquisa de produtos da API Vision

A Pesquisa de produtos da API Vision é um recurso do Google Cloud que permite aos usuários pesquisar produtos visualmente semelhantes em um catálogo. Os varejistas podem criar produtos, cada um contendo imagens de referência que descrevem visualmente o produto com base em um conjunto de pontos de vista. Em seguida, é possível adicionar esses produtos a conjuntos de produtos (ou seja, catálogo de produtos). No momento, a pesquisa de produtos da API Vision é compatível com as seguintes categorias: utilidades domésticas, vestuário, brinquedos, produtos embalados e produtos em geral.

Quando os usuários consultam o conjunto de produtos com suas próprias imagens, a pesquisa de produtos da API Vision aplica o machine learning para comparar o produto na imagem de consulta do usuário com as imagens no conjunto de produtos do varejista e retornar uma lista classificada de resultados visual e semanticamente similares.

3. Fazer o download e executar o app inicial

Fazer o download do código

Clique no link abaixo para fazer o download de todo o código para este codelab:

Descompacte o arquivo ZIP transferido por download. Isso descompacta uma pasta raiz (odml-pathways-main) com todos os recursos necessários. Neste codelab, você só vai precisar das fontes no subdiretório product-search/codelab2/android.

O subdiretório codelab2 no repositório odml-pathways contém dois diretórios:

  • android_studio_folder.pngstarter: o código inicial que você vai usar como base neste codelab.
  • android_studio_folder.pngfinal: código completo do app de exemplo finalizado.

O app inicial aqui é o que você criou no codelab Detectar objetos em imagens para criar uma pesquisa visual de produtos: Android. Ele usa a detecção e o rastreamento de objetos do Kit de ML para detectar objetos em uma imagem e mostrá-los na tela.

Importar o app para o Android Studio

Comece importando o app starter para o Android Studio.

No Android Studio, selecione Import Project (Gradle, Eclipse ADT etc.) e escolha a pasta starter no código-fonte que você baixou anteriormente.

7c0f27882a2698ac.png

Executar o app inicial

Agora que você importou o projeto para o Android Studio, está tudo pronto para executar o app pela primeira vez. Conecte o dispositivo Android via USB ao host ou inicie o emulador do Android Studio e clique em Executar ( execute.png) na barra de ferramentas do Android Studio.

Se esse botão estiver desativado, importe apenas starter/app/build.gradle, não o repositório inteiro.

O app será iniciado no seu dispositivo Android. Ele já tem a capacidade de detecção de objetos: detecta itens de moda na imagem e mostra onde eles estão. Teste com as fotos predefinidas para confirmar.

c6102a808fdfcb11.png

Captura de tela do app inicial, que pode detectar objetos em uma imagem

Em seguida, você vai estender o app para enviar os objetos detectados ao back-end da Pesquisa de produtos da API Vision e mostrar os resultados da pesquisa na tela.

4. Processar a seleção de objetos

Permitir que os usuários toquem em um objeto detectado para selecionar

Agora você vai adicionar um código para permitir que os usuários selecionem um objeto na imagem e iniciem a pesquisa de produtos. O app inicial já tem a capacidade de detectar objetos na imagem. É possível que haja vários objetos na imagem ou que o objeto detectado ocupe apenas uma pequena parte dela. Portanto, é necessário que o usuário toque em um dos objetos detectados para indicar qual deles ele quer usar na pesquisa de produtos.

9cdfcead6d95a87.png

Uma captura de tela dos itens de moda detectados na imagem

Para manter o codelab simples e focado no aprendizado de máquina, algum código Android clichê foi implementado no app inicial para ajudar você a detectar em qual objeto o usuário tocou. A visualização que mostra a imagem na atividade principal (ObjectDetectorActivity) é, na verdade, uma visualização personalizada (ImageClickableView) que estende o ImageView padrão do SO Android. Ele implementa alguns métodos utilitários convenientes, incluindo:

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) Este é um callback para receber a imagem cortada que contém apenas o objeto em que o usuário tocou. Você vai enviar essa imagem cortada para o back-end de pesquisa de produtos.

Adicione um código para processar o toque do usuário nos objetos detectados.

Acesse o método initViews na classe ObjectDetectorActivity e adicione estas linhas ao final do método: (o Android Studio vai informar que não é possível encontrar o método startProductImageSearch. Não se preocupe, você vai implementar isso um pouco mais tarde.)

// Callback received when the user taps on any of the detected objects.
ivPreview.setOnObjectClickListener { objectImage ->
    startProductImageSearch(objectImage)
}

O onObjectClickListener é chamado sempre que o usuário toca em um dos objetos detectados na tela. Ele recebe a imagem cortada que contém apenas o objeto selecionado. Por exemplo, se o usuário tocar na pessoa usando o vestido à direita, o listener será acionado com objectImage, conforme mostrado abaixo.

9cac8458d0f326e6.png

Um exemplo da imagem cortada transmitida ao onObjectClickListener

Enviar a imagem cortada para a atividade de pesquisa de produtos

Agora você vai implementar a lógica de envio da imagem de consulta ao back-end da Pesquisa de produtos da API Vision em uma atividade separada (ProductSearchActivity).

Todos os componentes da interface foram implementados com antecedência para que você possa se concentrar em escrever o código para se comunicar com o back-end de pesquisa de produtos.

25939f5a13eeb3c3.png

Uma captura de tela dos componentes da interface em ProductSearchActivity

Adicione um código para enviar a imagem do objeto selecionado pelo usuário ao ProductSearchActivity.

Volte ao Android Studio e adicione este método startProductImageSearch à classe ObjectDetectorActivity:

private fun startProductImageSearch(objectImage: Bitmap) {
    try {
        // Create file based Bitmap. We use PNG to preserve the image quality
        val savedFile = createImageFile(ProductSearchActivity.CROPPED_IMAGE_FILE_NAME)
        objectImage.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(savedFile))

        // Start the product search activity (using Vision Product Search API.).
        startActivity(
            Intent(
                    this,
                    ProductSearchActivity::class.java
            ).apply {
                // As the size limit of a bundle is 1MB, we need to save the bitmap to a file
                // and reload it in the other activity to support large query images.
                putExtra(
                    ProductSearchActivity.REQUEST_TARGET_IMAGE_PATH,
                    savedFile.absolutePath
                )
            })
    } catch (e: Exception) {
        // IO Exception, Out Of memory ....
        Toast.makeText(this, e.message, Toast.LENGTH_SHORT).show()
        Log.e(TAG, "Error starting the product image search activity.", e)
    }
}

O snippet de código faz três coisas:

  • Pega a imagem cortada e a serializa em um arquivo PNG.
  • Inicia o ProductSearchActivity para executar a sequência de pesquisa de produtos.
  • Inclui o URI da imagem cortada na intent de início de atividade para que ProductSearchActivity possa recuperá-la mais tarde e usar como imagem de consulta.

Alguns pontos merecem atenção:

  • A lógica para detectar objetos e consultar o back-end foi dividida em apenas duas atividades para facilitar a compreensão do codelab. Cabe a você decidir como implementá-las no app.
  • Você precisa gravar a imagem de consulta em um arquivo e transmitir o URI da imagem entre atividades, porque ela pode ser maior que o limite de tamanho de 1 MB de uma intent do Android.
  • Você pode armazenar a imagem de consulta em PNG porque é um formato sem perda de dados.

Recuperar a imagem da consulta na atividade de pesquisa de produtos

No ProductSearchActivity, o código para extrair a imagem da consulta e mostrá-la na tela já foi implementado no app inicial.

Acesse o método onCreate e confirme se este código já está lá:

// Receive the query image and show it on the screen
intent.getStringExtra(REQUEST_TARGET_IMAGE_PATH)?.let { absolutePath ->
    viewBinding.ivQueryImage.setImageBitmap(BitmapFactory.decodeFile(absolutePath))
}

Executar o app

Agora clique em Executar ( execute.png) na barra de ferramentas do Android Studio.

Quando o app carregar, toque em qualquer uma das imagens predefinidas e selecione um dos objetos detectados.

Confirme se o ProductSearchActivity aparece com a imagem em que você tocou. O botão Pesquisar ainda não faz nada, mas vamos implementá-lo em seguida.

fed40f81b8b43801.png

Uma tela semelhante vai aparecer depois que você tocar em um dos objetos detectados.

5. Conheça o back-end da pesquisa de produtos

Criar o back-end de pesquisa de imagem de produto

Este codelab exige um back-end de pesquisa de produtos criado com a Pesquisa de produtos da API Vision. Há duas opções para fazer isso:

Opção 1: usar o back-end de demonstração implantado para você

Você pode continuar este codelab usando o back-end de pesquisa de produtos que o Google já implantou para você. O back-end de demonstração pode ser replicado seguindo o início rápido da Pesquisa de produtos da API Vision.

Opção 2: crie seu próprio back-end seguindo o guia de início rápido da Pesquisa de produtos da API Vision

Essa opção é recomendada para quem quer aprender em detalhes como criar um back-end de pesquisa de produtos para criar um catálogo próprio mais tarde. Você precisa ter o seguinte:

  • Uma conta do Google Cloud com o faturamento ativado. (Pode ser uma conta de teste sem custo financeiro.)
  • Conhecimento sobre conceitos do Google Cloud, incluindo projetos, contas de serviço etc.

Você vai aprender a fazer isso mais adiante no programa de aprendizado.

Aprenda os conceitos importantes

Você vai encontrar estes conceitos ao interagir com o back-end de pesquisa de produtos:

  • Conjunto de produtos: um contêiner simples para um grupo de produtos. Um catálogo de produtos pode ser representado como um conjunto de produtos e os itens dele.
  • Produto: depois de criar um conjunto de produtos, você pode criar produtos e adicioná-los ao conjunto.
  • Imagens de referência do produto: são imagens com diversas visualizações dos produtos. Elas são usadas para pesquisar produtos visualmente semelhantes.
  • Pesquisar produtos: depois de criar e indexar o conjunto de produtos, é possível consultá-lo usando a API Cloud Vision.

Entender o catálogo de produtos predefinido

O back-end de demonstração da pesquisa de produtos usado neste codelab foi criado com a Pesquisa de produtos da API Vision e um catálogo de produtos com cerca de cem imagens de sapatos e vestidos. Confira algumas imagens do catálogo:

4f1a8507b74ab178.png 79a5fc6c829eca77.png 3528c872f813826e.png

Exemplos do catálogo de produtos predefinido

Chamar o back-end de demonstração da pesquisa de produtos

É possível chamar a pesquisa de produtos da API Vision diretamente de um app para dispositivos móveis. Para isso, configure uma chave de API do Google Cloud e restrinja o acesso a ela apenas ao seu app.

Para simplificar este codelab, um endpoint de proxy foi configurado para permitir o acesso ao back-end de demonstração sem se preocupar com a chave de API e a autenticação. Ele recebe a solicitação HTTP do app para dispositivos móveis, anexa a chave de API e encaminha a solicitação para o back-end da Pesquisa de produtos da API Vision. Em seguida, o proxy recebe a resposta do back-end e a retorna para o app para dispositivos móveis.

Neste codelab, você vai usar duas APIs da Pesquisa de produtos da API Vision:

6. Implementar o cliente da API

Entender o fluxo de trabalho de pesquisa de produtos

Siga este fluxo de trabalho para fazer a pesquisa de produtos com o back-end:

Implementar a classe de cliente da API

Agora você vai implementar o código para chamar o back-end de pesquisa de produtos em uma classe dedicada chamada ProductSearchAPIClient. Alguns códigos clichês foram implementados para você no app inicial:

  • class ProductSearchAPIClient: essa classe está quase vazia agora, mas tem alguns métodos que você vai implementar mais tarde neste codelab.
  • fun convertBitmapToBase64(bitmap: Bitmap): converta uma instância de bitmap na representação base64 dela para enviar ao back-end de pesquisa de produtos.
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>: chame a API projects.locations.images.annotate e analise a resposta.
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult>: chame a API projects.locations.products.referenceImages.get e analise a resposta.
  • SearchResult.kt: esse arquivo contém várias classes de dados para representar os tipos retornados pelo back-end da pesquisa de produtos da API Vision.

Especificar as configurações da API

Acesse a classe ProductSearchAPIClient e confira algumas configurações do back-end de pesquisa de produtos já definidas:

// Define the product search backend
// Option 1: Use the demo project that we have already deployed for you
const val VISION_API_URL =
    "https://us-central1-odml-codelabs.cloudfunctions.net/productSearch"
const val VISION_API_KEY = ""
const val VISION_API_PROJECT_ID = "odml-codelabs"
const val VISION_API_LOCATION_ID = "us-east1"
const val VISION_API_PRODUCT_SET_ID = "product_set0"
  • VISION_API_URL é o endpoint da API Cloud Vision. Ao continuar com o back-end de demonstração, defina isso como o endpoint do proxy. No entanto, se você implantar seu próprio back-end, será necessário mudar para o endpoint da API Cloud Vision. https://vision.googleapis.com/v1.
  • VISION_API_KEY é a chave de API do seu projeto do Google Cloud. Como o proxy já processa a autenticação, deixe em branco.
  • VISION_API_PROJECT_ID é o ID do projeto do Cloud. odml-codelabs é o projeto do Cloud em que o back-end de demonstração é implantado.
  • VISION_API_LOCATION_ID é o local do Google Cloud em que o back-end de pesquisa de produtos é implantado. us-east1 é onde implantamos o back-end de demonstração.
  • VISION_API_PRODUCT_SET_ID é o ID do catálogo de produtos (também conhecido como "conjunto de produtos" no termo da API Vision) em que você quer pesquisar produtos visualmente semelhantes. É possível ter vários catálogos em um projeto do Cloud. product_set0 é o catálogo de produtos predefinido do back-end de demonstração.

7. Chamar a API Product Search

Conheça o formato de solicitação e resposta da API

É possível encontrar produtos semelhantes a uma determinada imagem. Passe o URI do Google Cloud Storage da imagem, o URL da Web ou a string codificada em base64 para a Pesquisa de produtos da API Vision. Neste codelab, você vai usar a opção de string codificada em base64, já que a imagem de consulta só existe no dispositivo do usuário.

É necessário enviar uma solicitação POST ao endpoint projects.locations.images.annotate com este corpo JSON de solicitação:

{
  "requests": [
    {
      "image": {
        "content": {base64-encoded-image}
      },
      "features": [
        {
          "type": "PRODUCT_SEARCH",
          "maxResults": 5
        }
      ],
      "imageContext": {
        "productSearchParams": {
          "productSet": "projects/{project-id}/locations/{location-id}/productSets/{product-set-id}",
          "productCategories": [
               "apparel-v2"
          ],
        }
      }
    }
  ]
}

Há alguns parâmetros que precisam ser especificados:

  • base64-encoded-image: a representação em base64 (string ASCII) dos dados binários da imagem de consulta.
  • project-id: o ID do projeto do GCP.
  • location-id: um identificador de local válido.
  • product-set-id: o ID do conjunto de produtos em que você quer executar a operação.

Como seu catálogo de produtos contém apenas imagens de sapatos e vestidos, especifique productCategories como apparel-v2. v2 significa que usamos a versão 2 do modelo de machine learning de pesquisa de produtos de vestuário.

Quando a solicitação é bem-sucedida, o servidor retorna um código de status HTTP 200 OK e a resposta no formato JSON. A resposta JSON inclui os dois tipos de resultados a seguir:

  • productSearchResults: contém uma lista de produtos correspondentes para a imagem inteira.
  • productGroupedResults: contém as coordenadas da caixa delimitadora e os itens correspondentes de cada produto identificado na imagem.

Como o produto já foi cortado da imagem original, você vai analisar os resultados na lista productSearchResults.

Confira alguns campos importantes no objeto de resultado da pesquisa de produtos:

  • product.name: o identificador exclusivo de um produto no formato projects/{project-id}/locations/{location-id}/products/{product_id}
  • product.score: um valor que indica o grau de semelhança entre o resultado da pesquisa e a imagem da consulta. Valores mais altos significam mais similaridade.
  • product.image: o identificador exclusivo da imagem de referência de um produto no formato projects/{project-id}/locations/{location-id}/products/{product_id}/referenceImages/{image_id}. Você precisará enviar outra solicitação de API para projects.locations.products.referenceImages.get e receber o URL da imagem de referência para que ela seja exibida na tela.
  • product.labels: uma lista de tags predefinidas do produto. Isso é útil se você quiser filtrar os resultados da pesquisa para mostrar apenas uma categoria de roupas, como vestidos.

Converter a imagem de consulta em base64

É necessário converter a imagem de consulta na representação de string base64 e anexar a string ao objeto JSON no corpo da solicitação.

Acesse a classe ProductSearchAPIClient, encontre o método convertBitmapToBase64 vazio e substitua-o por esta implementação:

private fun convertBitmapToBase64(bitmap: Bitmap): String {
    val byteArrayOutputStream = ByteArrayOutputStream()
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
    val byteArray: ByteArray = byteArrayOutputStream.toByteArray()
    return Base64.encodeToString(byteArray, Base64.DEFAULT)
}

Implementar a chamada de API

Em seguida, crie uma solicitação da API de pesquisa de produtos e envie para o back-end. Você vai usar o Volley para fazer a solicitação de API e retornar o resultado usando a API Task.

Volte para a classe ProductSearchAPIClient, encontre o método annotateImage vazio e substitua-o por esta implementação:

fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>> {
    // Initialization to use the Task API
    val apiSource = TaskCompletionSource<List<ProductSearchResult>>()
    val apiTask = apiSource.task

    // Convert the query image to its Base64 representation to call the Product Search API.
    val base64: String = convertBitmapToBase64(image)

    // Craft the request body JSON.
    val requestJson = """
        {
          "requests": [
            {
              "image": {
                "content": """".trimIndent() + base64 + """"
              },
              "features": [
                {
                  "type": "PRODUCT_SEARCH",
                  "maxResults": $VISION_API_PRODUCT_MAX_RESULT
                }
              ],
              "imageContext": {
                "productSearchParams": {
                  "productSet": "projects/${VISION_API_PROJECT_ID}/locations/${VISION_API_LOCATION_ID}/productSets/${VISION_API_PRODUCT_SET_ID}",
                  "productCategories": [
                       "apparel-v2"
                     ]
                }
              }
            }
          ]
        }
    """.trimIndent()

    // Add a new request to the queue
    requestQueue.add(object :
        JsonObjectRequest(
            Method.POST,
            "$VISION_API_URL/images:annotate?key=$VISION_API_KEY",
            JSONObject(requestJson),
            { response ->
                // Parse the API JSON response to a list of ProductSearchResult object/
                val productList = apiResponseToObject(response)

                // Return the list.
                apiSource.setResult(productList)
            },
            // Return the error
            { error -> apiSource.setException(error) }
        ) {
        override fun getBodyContentType() = "application/json"
    }.apply {
        setShouldCache(false)
    })

    return apiTask
}

Mostrar o resultado da pesquisa na interface

Agora o código da API em ProductSearchAPIClient está pronto. Volte para a atividade ProductSearchActivity e implemente o código da interface.

A atividade já tem um código clichê que aciona o método searchByImage(queryImage: Bitmap). Adicione código para chamar o back-end e mostrar os resultados na interface a esse método atualmente vazio.

apiClient.annotateImage(queryImage)
    .addOnSuccessListener { showSearchResult(it) }
    .addOnFailureListener { error ->
        Log.e(TAG, "Error calling Vision API Product Search.", error)
        showErrorResponse(error.localizedMessage)
    }

O método showSearchResult contém um código clichê que analisa a resposta da API e a mostra na tela.

Executar

Agora clique em Executar ( execute.png) na barra de ferramentas do Android Studio. Depois que o app carregar, toque em qualquer imagem predefinida, selecione um objeto detectado, toque no botão Pesquisar e confira os resultados da pesquisa retornados do back-end. Você verá algo como:

bb5e7c27c283a2fe.png

Captura de tela da tela de resultados da pesquisa de produtos

O back-end já retorna uma lista de produtos visualmente semelhantes do catálogo de produtos predefinido. No entanto, você pode ver que a imagem do produto ainda está vazia. Isso acontece porque o endpoint projects.locations.images.annotate só retorna IDs de imagens de produtos, como projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77. Você precisará fazer outra chamada de API para o endpoint projects.locations.products.referenceImages.get e receber o URL dessa imagem de referência para mostrá-la na tela.

8. Receber as imagens de referência do produto

Conheça o formato de solicitação e resposta da API

Envie uma solicitação GET HTTP com um corpo de solicitação vazio para o endpoint projects.locations.products.referenceImages.get e receba os URIs das imagens de produtos retornadas pelo endpoint de pesquisa de produtos.

A solicitação HTTP é assim:

GET $VISION_API_URL/projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77?key=$VISION_API_KEY

Quando a solicitação é bem-sucedida, o servidor retorna um código de status HTTP 200 OK e a resposta no formato JSON, conforme abaixo:

{
  "name":"projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77",
  "uri":"gs://cloud-ai-vision-data/product-search-tutorial/images/46991e7370ba11e8a1bbd20059124800.jpg"
}
  • name: o identificador da imagem de referência.
  • uri: o URI da imagem no Google Cloud Storage (GCS).

As imagens de referência do back-end de pesquisa de produtos de demonstração foram configuradas para ter permissão de leitura pública. Portanto, é fácil converter o URI do GCS em um URL HTTP e mostrar na interface do app. Basta substituir o prefixo gs:// por https://storage.googleapis.com/.

Implementar a chamada de API

Em seguida, crie uma solicitação da API de pesquisa de produtos e envie para o back-end. Você vai usar o Volley e a API Task de maneira semelhante à chamada da API de pesquisa de produtos.

Volte para a classe ProductSearchAPIClient, encontre o método fetchReferenceImage vazio e substitua-o por esta implementação:

private fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult> {
    // Initialization to use the Task API
    val apiSource = TaskCompletionSource<ProductSearchResult>()
    val apiTask = apiSource.task

    // Craft the API request to get details about the reference image of the product
    val stringRequest = object : StringRequest(
        Method.GET,
        "$VISION_API_URL/${searchResult.imageId}?key=$VISION_API_KEY",
        { response ->
            val responseJson = JSONObject(response)
            val gcsUri = responseJson.getString("uri")

            // Convert the GCS URL to its HTTPS representation
            val httpUri = gcsUri.replace("gs://", "https://storage.googleapis.com/")

            // Save the HTTPS URL to the search result object
            searchResult.imageUri = httpUri

            // Invoke the listener to continue with processing the API response (eg. show on UI)
            apiSource.setResult(searchResult)
        },
        { error -> apiSource.setException(error) }
    ) {

        override fun getBodyContentType(): String {
            return "application/json; charset=utf-8"
        }
    }
    Log.d(ProductSearchActivity.TAG, "Sending API request.")

    // Add the request to the RequestQueue.
    requestQueue.add(stringRequest)

    return apiTask
}

Esse método usa um objeto searchResult: ProductSearchResult retornado pelo endpoint de pesquisa de produtos e segue estas etapas:

  1. Chama o endpoint da imagem de referência para receber o URI do GCS da imagem de referência.
  2. Converte o URI do GCS em um URL HTTP.
  3. Atualiza a propriedade httpUri do objeto searchResult com esse URL HTTP.

Conecte as duas solicitações de API

Volte para annotateImage e modifique-o para receber todos os URLs HTTP das imagens de referência antes de retornar a lista ProductSearchResult para o chamador.

Encontre esta linha:

// Return the list.
apiSource.setResult(productList)

Em seguida, substitua por esta implementação:

// Loop through the product list and create tasks to load reference images.
// We will call the projects.locations.products.referenceImages.get endpoint
// for each product.
val fetchReferenceImageTasks = productList.map { fetchReferenceImage(it) }

// When all reference image fetches have completed,
// return the ProductSearchResult list
Tasks.whenAllComplete(fetchReferenceImageTasks)
    // Return the list of ProductSearchResult with product images' HTTP URLs.
    .addOnSuccessListener { apiSource.setResult(productList) }
    // An error occurred so returns it to the caller.
    .addOnFailureListener { apiSource.setException(it) }

O código boilerplate para mostrar as imagens de referência na tela já foi implementado na classe ProductSearchAdapter. Portanto, você pode executar o app novamente.

Executar

Agora clique em Executar ( execute.png) na barra de ferramentas do Android Studio. Quando o app carregar, toque em qualquer uma das imagens predefinidas, selecione um objeto detectado e toque no botão Pesquisar para ver os resultados da pesquisa, desta vez com as imagens dos produtos.

Os resultados da pesquisa de produtos fazem sentido para você?

25939f5a13eeb3c3.png

9. Parabéns!

Você aprendeu a chamar um back-end da Pesquisa de produtos da API Vision para adicionar a capacidade de pesquisa de imagens de produtos ao seu app Android. Isso é tudo o que você precisa para começar!

Ao continuar, talvez você queira criar seu próprio back-end usando seu catálogo de produtos. Confira o próximo codelab no programa de aprendizado Pesquisa de imagens de produtos para saber como criar seu próprio back-end e configurar a chave de API para chamá-lo de um app para dispositivos móveis.

O que vimos

  • Como chamar o back-end da Pesquisa de produtos da API Vision de um app Android

Próximas etapas

Saiba mais