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