¿Cómo crear una aplicación Google Lens en Android?

Hemos visto la nueva aplicación Google Lens en la que podemos capturar imágenes de cualquier producto y a partir de esa imagen podemos llegar a ver los resultados de búsqueda de ese producto que mostraremos dentro de nuestra aplicación. 

¿Qué vamos a construir en este artículo? 

Construiremos una aplicación simple en la que capturaremos una imagen de la cámara de nuestro dispositivo y luego haremos clic en el botón para obtener los resultados de ese producto.

Implementación paso a paso

Paso 1: crear un nuevo proyecto

Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Java como lenguaje de programación.

Paso 2: conecta tu aplicación a Firebase

Después de crear un nuevo proyecto en Android Studio, conecte su aplicación a Firebase. Para conectar su aplicación a firebase. Navegue a Herramientas en la barra superior. Después de eso, haga clic en Firebase. Se abrirá una nueva ventana en el lado derecho. Dentro de esa ventana, haga clic en Firebase ML y luego haga clic en Usar el kit Firebase ML en Android. Puede ver la opción en la siguiente captura de pantalla.  

Después de hacer clic en esta opción, verá la siguiente pantalla. En esta pantalla, haga clic en la opción Conectar a Firebase para conectar su aplicación a Firebase. Verá la siguiente pantalla.  

Haga clic en la opción Conectar para conectar su aplicación a Firebase y agregue la siguiente dependencia a su archivo build.gradle .  

Paso 3: Agregar dependencia para la traducción de idiomas al archivo build.gradle

Vaya a la aplicación > Gradle Scripts > archivo build.gradle y agréguele el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

// Dependencias de base de fuego.

implementación ‘com.google.firebase:firebase-core:15.0.2’

implementación ‘com.google.firebase:firebase-ml-vision:24.0.3’

implementación ‘com.google.firebase:firebase-ml-vision-image-label-model:20.0.1’

// la línea de abajo se usa para la biblioteca volley

implementación ‘com.android.volley:volley:1.1.1’

// la línea de abajo se usa para la biblioteca de carga de imágenes

implementación ‘com.squareup.picasso:picasso:2.71828’

Paso 4: agregar permisos para acceder a Internet y metadatos en su archivo AndroidManifest de aplicaciones de Android

Vaya a la aplicación > archivo AndroidManifest.xml y agréguele el siguiente código. Se agregan comentarios en el código para conocer con más detalle. 

XML

<!-- below line is use to add camera feature in our app -->
<uses-feature
  android:name="android.hardware.camera"
  android:required="true" />
<!-- permission for internet -->
<uses-permission android:name="android.permission.INTERNET" />

Agregue la siguiente línea dentro de la etiqueta de su aplicación.  

XML

<meta-data
  android:name="com.google.firebase.ml.vision.DEPENDENCIES"
  android:value="label" />

A continuación se muestra el código completo para el archivo AndroidManifest.xml :

XML

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.googlelens">
  
    <!-- below line is use to add camera feature in our app -->
    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />
    <!-- permission for internet -->
    <uses-permission android:name="android.permission.INTERNET" />
  
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.GoogleLens">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
  
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  
        <meta-data
            android:name="com.google.firebase.ml.vision.DEPENDENCIES"
            android:value="label" />
  
    </application>
  
</manifest>

Paso 5: trabajar con el archivo activity_main.xml

aplicación > res > diseño > actividad_principal.xml actividad_principal.xml

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
      
    <!--image view for displaying our image-->
    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:scaleType="centerCrop" />
  
    <LinearLayout
        android:id="@+id/idLLButtons"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/image"
        android:orientation="horizontal">
  
        <!--button for capturing our image-->
        <Button
            android:id="@+id/snapbtn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="5dp"
            android:layout_marginTop="30dp"
            android:layout_weight="1"
            android:lines="2"
            android:text="Snap"
            android:textAllCaps="false"
            android:textSize="18sp"
            android:textStyle="bold" />
  
        <!--button for detecting the objects-->
        <Button
            android:id="@+id/idBtnSearchResuts"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="5dp"
            android:layout_marginTop="30dp"
            android:layout_weight="1"
            android:lines="2"
            android:text="Get Search Ressults"
            android:textAllCaps="false"
            android:textSize="18sp"
            android:textStyle="bold" />
  
    </LinearLayout>
  
    <!--recycler view for displaying the list of result-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/idRVSearchResults"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/idLLButtons" />
      
</RelativeLayout>

Paso 6: Crear una clase modal para almacenar nuestros datos

Vaya a la aplicación > java > el nombre del paquete de su aplicación > haga clic con el botón derecho en él > Nuevo > clase Java y nombre su clase como DataModal y agréguele el siguiente código.

Java

public class DataModal {
      
    // title for our search result.
    private String title;
      
    // link of our search result.
    private String link;
      
    // display link for our search result.
    private String displayed_link;
      
    // snippet for our search result.
    private String snippet;
  
    // constructor class.
    public DataModal(String title, String link, String displayed_link, String snippet) {
        this.title = title;
        this.link = link;
        this.displayed_link = displayed_link;
        this.snippet = snippet;
    }
  
    // getter and setter methods.
    public String getTitle() {
        return title;
    }
  
    public void setTitle(String title) {
        this.title = title;
    }
  
    public String getLink() {
        return link;
    }
  
    public void setLink(String link) {
        this.link = link;
    }
  
    public String getDisplayed_link() {
        return displayed_link;
    }
  
    public void setDisplayed_link(String displayed_link) {
        this.displayed_link = displayed_link;
    }
  
    public String getSnippet() {
        return snippet;
    }
  
    public void setSnippet(String snippet) {
        this.snippet = snippet;
    }
}

Paso 7: Creación de un archivo de diseño para mostrar nuestros elementos de RecyclerView 

Vaya a la aplicación > res > diseño > haga clic con el botón derecho en él > Nuevo > archivo de recursos de diseño y asígnele el nombre search_result_rv_item y agréguele el siguiente código.   

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    android:elevation="8dp"
    app:cardCornerRadius="8dp">
  
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
  
        <!--text view for our title-->
        <TextView
            android:id="@+id/idTVTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="Title"
            android:textColor="@android:color/holo_blue_dark"
            android:textSize="15sp" />
  
        <!--text view for our snippet-->
        <TextView
            android:id="@+id/idTVSnippet"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="Snippet"
            android:textAllCaps="false"
            android:textColor="@android:color/darker_gray"
            android:textSize="12sp" />
  
        <!--text view for our description-->
        <TextView
            android:id="@+id/idTVDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="3dp"
            android:text="Description"
            android:textColor="@android:color/darker_gray"
            android:textSize="12sp" />
  
    </LinearLayout>
      
</androidx.cardview.widget.CardView>

Paso 8: crear una clase de adaptador para nuestro RecyclerView

Vaya a la aplicación > java > el nombre del paquete de su aplicación > haga clic con el botón derecho en él > Nuevo > clase Java y asígnele el nombre SearchResultsRVAdapter y agréguele el siguiente código. 

Java

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
  
import java.util.ArrayList;
  
public class SearchResultsRVAdapter extends RecyclerView.Adapter<SearchResultsRVAdapter.ViewHolder> {
      
    // arraylist for storing our data and context
    private ArrayList<DataModal> dataModalArrayList;
    private Context context;
      
    // constructor for our variables.
    public SearchResultsRVAdapter(ArrayList<DataModal> dataModalArrayList, Context context) {
        this.dataModalArrayList = dataModalArrayList;
        this.context = context;
    }
  
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // inside on create view holder method we are inflating our layout file which we created.
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_result_rv_item, parent, false);
        return new ViewHolder(view);
    }
  
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        // inside on bind view holder method we are setting
        // data to each item of recycler view.
        DataModal modal = dataModalArrayList.get(position);
        holder.titleTV.setText(modal.getTitle());
        holder.snippetTV.setText(modal.getDisplayed_link());
        holder.descTV.setText(modal.getSnippet());
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // opening a link in your browser.
                Intent i = new Intent(Intent.ACTION_VIEW);
                i.setData(Uri.parse(modal.getLink()));
                context.startActivity(i);
            }
        });
    }
  
    @Override
    public int getItemCount() {
        // returning the size of array list.
        return dataModalArrayList.size();
    }
  
    public class ViewHolder extends RecyclerView.ViewHolder {
        // creating variables for our text view.
        private TextView titleTV, descTV, snippetTV;
  
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            // initializing our views with their ids.
            titleTV = itemView.findViewById(R.id.idTVTitle);
            descTV = itemView.findViewById(R.id.idTVDescription);
            snippetTV = itemView.findViewById(R.id.idTVSnippet);
  
        }
    }
}

Paso 9: Generación de su clave API

Ingresa al sitio https://serpapi.com/search-api y crea tu cuenta con tu cuenta de Google. Este es un proceso similar al registrarse en Geeks for Geeks. Mientras genera su clave API, asegúrese de seleccionar la opción de prueba gratuita y continúe. Después de ir al sitio que se muestra arriba, verá la siguiente pantalla. Simplemente inicie sesión con sus credenciales y continúe.

Después de continuar, simplemente debe navegar a la opción Mi cuenta> Panel para abrir la pantalla a continuación. En esta pantalla, podrá ver su clave API.

Paso 10: trabajar con el archivo MainActivity.java

Vaya al archivo MainActivity.java y consulte el siguiente código. A continuación se muestra el código del archivo MainActivity.java . Se agregan comentarios dentro del código para comprender el código con más detalle.

Java

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
  
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.ml.vision.FirebaseVision;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.label.FirebaseVisionImageLabel;
import com.google.firebase.ml.vision.label.FirebaseVisionImageLabeler;
  
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
  
import java.util.ArrayList;
import java.util.List;
  
public class MainActivity extends AppCompatActivity {
  
    static final int REQUEST_IMAGE_CAPTURE = 1;
      
    // variables for our image view, image bitmap, 
    // buttons, recycler view, adapter and array list.
    private ImageView img;
    private Button snap, searchResultsBtn;
    private Bitmap imageBitmap;
    private RecyclerView resultRV;
    private SearchResultsRVAdapter searchResultsRVAdapter;
    private ArrayList<DataModal> dataModalArrayList;
    private String title, link, displayed_link, snippet;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
          
        // initializing all our variables for views
        img = (ImageView) findViewById(R.id.image);
        snap = (Button) findViewById(R.id.snapbtn);
        searchResultsBtn = findViewById(R.id.idBtnSearchResuts);
        resultRV = findViewById(R.id.idRVSearchResults);
          
        // initializing our array list
        dataModalArrayList = new ArrayList<>();
          
        // initializing our adapter class.
        searchResultsRVAdapter = new SearchResultsRVAdapter(dataModalArrayList, MainActivity.this);
          
        // layout manager for our recycler view.
        LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false);
          
        // on below line we are setting layout manager 
        // and adapter to our recycler view.
        resultRV.setLayoutManager(manager);
        resultRV.setAdapter(searchResultsRVAdapter);
  
        // adding on click listener for our snap button.
        snap.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // calling a method to capture an image.
                dispatchTakePictureIntent();
            }
        });
          
        // adding on click listener for our button to search data.
        searchResultsBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // calling a method to get search results.
                getResults();
            }
        });
    }
  
    private void getResults() {
        // inside the label image method we are calling a firebase vision image
        // and passing our image bitmap to it.
        FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(imageBitmap);
          
        // on below line we are creating a labeler for our image bitmap and 
        // creating a variable for our firebase vision image labeler.
        FirebaseVisionImageLabeler labeler = FirebaseVision.getInstance().getOnDeviceImageLabeler();
          
        // calling a method to process an image and adding on success listener method to it.
        labeler.processImage(image).addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionImageLabel>>() {
            @Override
            public void onSuccess(List<FirebaseVisionImageLabel> firebaseVisionImageLabels) {
                String searchQuery = firebaseVisionImageLabels.get(0).getText();
                searchData(searchQuery);
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // displaying error message.
                Toast.makeText(MainActivity.this, "Fail to detect image..", Toast.LENGTH_SHORT).show();
            }
        });
    }
  
    private void searchData(String searchQuery) {
        String apiKey = "Enter your API key here";
        String url = "https://serpapi.com/search.json?q=" + searchQuery.trim() + "&location=Delhi,India&hl=en&gl=us&google_domain=google.com&api_key=" + apiKey;
          
        // creating a new variable for our request queue
        RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    // on below line we are extracting data from our json.
                    JSONArray organicResultsArray = response.getJSONArray("organic_results");
                    for (int i = 0; i < organicResultsArray.length(); i++) {
                        JSONObject organicObj = organicResultsArray.getJSONObject(i);
                        if (organicObj.has("title")) {
                            title = organicObj.getString("title");
                        }
                        if (organicObj.has("link")) {
                            link = organicObj.getString("link");
                        }
                        if (organicObj.has("displayed_link")) {
                            displayed_link = organicObj.getString("displayed_link");
                        }
                        if (organicObj.has("snippet")) {
                            snippet = organicObj.getString("snippet");
                        }
                        // on below line we are adding data to our array list.
                        dataModalArrayList.add(new DataModal(title, link, displayed_link, snippet));
                    }
                    // notifying our adapter class 
                    // on data change in array list.
                    searchResultsRVAdapter.notifyDataSetChanged();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // displaying error message.
                Toast.makeText(MainActivity.this, "No Result found for the search query..", Toast.LENGTH_SHORT).show();
            }
        });
        // adding json object request to our queue.
        queue.add(jsonObjectRequest);
    }
  
    // method to capture image.
    private void dispatchTakePictureIntent() {
        // inside this method we are calling an implicit intent to capture an image.
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // calling a start activity for result when image is captured.
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }
  
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // inside on activity result method we are 
        // setting our image to our image view from bitmap.
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            imageBitmap = (Bitmap) extras.get("data");
            // on below line we are setting our
            // bitmap to our image view.
            img.setImageBitmap(imageBitmap);
        }
    }
}

Ahora ejecute su aplicación y vea el resultado de la aplicación. Asegúrese de cambiar su clave API antes de ejecutar la aplicación. 

Producción:

Publicación traducida automáticamente

Artículo escrito por chaitanyamunje y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *