No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Mostrar datos de la API en la aplicación

19/25
Recursos

Aportes 44

Preguntas 7

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Si llegaron al final de este video y no les muestra la imagen del gato y encima les sale un error como este: "Can’t get input stream from URL! "
Relájense, el error es básicamente por temas de seguridad ya que la imagen está en https y el sitio del api de gatitos no permite la descarga.
El código:
image = ImageIO.read(url);
ImageIcon fondoG = new ImageIcon(image);

Si funciona en http o https que no impida la descarga de la imagen (lo probé), una simple declaración de ulr no es suficiente para descargar la imagen protegida.
Esto me funcionó:
HttpURLConnection httpcon = (HttpURLConnection)url.openConnection();
httpcon.addRequestProperty(“User-Agent”, “”);
BufferedImage bufferedImage = ImageIO.read(httpcon.getInputStream());
ImageIcon fondoG = new ImageIcon(bufferedImage);

Creditos a un usuario de la siguiente clase.
Saludos!

Este es el codigo entero con la solucion del error Input Stream
`public static void verGatitos() throws IOException{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(“https://api.thecatapi.com/v1/images/search”)
.method(“GET”, null)
.build();
Response response = client.newCall(request).execute();

    String json = response.body().string();
    json = json.substring(1,json.length()-1);
    
    Gson gson = new Gson(); 
    Gatos gatos = gson.fromJson(json, Gatos.class);
    
    Image imagen = null;
    try{
        URL url = new URL(gatos.getUrl());
        HttpURLConnection http = (HttpURLConnection) url.openConnection();
        http.addRequestProperty("User-Agent", "");
        BufferedImage bufferedImage = ImageIO.read(http.getInputStream());
        ImageIcon fondoGato = new ImageIcon(bufferedImage);
        
        if(fondoGato.getIconWidth() > 800 || fondoGato.getIconHeight() > 400){
            
            Image fondo = fondoGato.getImage();
            Image modificada = fondo.getScaledInstance(800, 400, java.awt.Image.SCALE_SMOOTH);
            fondoGato = new ImageIcon(modificada);
        }   
            
        String menu =  "Opciones: \n1.- Cambiar Gatitos \n2.-Favorito \n3.-Volver ";
        String botones[] = { "Ver Otra imagen", "Favoritos", "Volver"};
        String id_gato = gatos.getID();
        String opcion = (String) JOptionPane.showInputDialog(null,menu,id_gato,JOptionPane.INFORMATION_MESSAGE
                ,fondoGato,botones,botones[0]);
        
        int seleccion = -1;
        
        for(int i = 0; i < botones.length;i++){
            if(opcion.equals(botones[i])){
                seleccion = i;
            }
        }
        
        switch(seleccion){
            case 0:
                verGatitos();
                break;
            case 1:
                favoritos(gatos);
                break;
            default:
                break;             
        }
        
    }catch(IOException e){
        System.out.println(e);
    }
      
    
}`


Creo que la API de gatitos esta experimentando problemas, asi que utilice una API de perritos les dejo el link:
https://dog.ceo/dog-api/

Profesor, el error de Can’t get input stream from URL! logre solucionarlo gracias al código que compartieron mas abajo que va debajo de la instancia del URL y antes del ImageIcon


HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.addRequestProperty("User-Agent", "");
BufferedImage bufferedImage = ImageIO.read(http.getInputStream());


investigue en Internet pero poco he encontrado, para los que sepan ingles, tengan el mismo error aquí algunas paginas que pueden aclararles un poco

https://www.programcreek.com/java-api-examples/?class=java.net.HttpURLConnection&method=addRequestProperty

https://www.codejava.net/java-se/networking/how-to-use-java-urlconnection-and-httpurlconnection

ahora podre seguir con el tutorial, pero, si no es mucho pedir, alguien podría explicar ese pedacito de código? o el por que algunos les funciona sin ese código y a otros no? Gracias, seguiré investigando si tengo la respuesta la compartiré.

Si les da el error:

method GET must not have a request body

cambien el .method(“GET”, body) por .get()

        Request request = new Request.Builder()
                .url("https://api.thecatapi.com/v1/images/search")
                .get()
                .build();

Estudiantes, actualicé el proyecto en mi repositorio aplicando mejores prácticas

Quien quiere ver gatos? lo de hoy son los memes, les dejo un proyecto en github que busca memes en reddit y devuelve un JSON con la información, este es el link de la API https://meme-api.herokuapp.com/gimme

Este es mi codigo:
MemeService

public class MemesService {
    public static void verMemes() throws IOException {
        ArrayList<String> options = new ArrayList<>();
        options.add(" 1. ver otro meme");
        options.add(" 2. abrir meme en chrome");
        options.add(" 3. favoritos");
        options.add(" 4. volver al menu");
        int op = -1;
        do {
            Meme meme = getMemeFromAPI();
            Object input = JOptionPane.showInputDialog(null, "Opciones: ", meme.getTitle()+" subreddit: "+meme.getSubreddit(), JOptionPane.INFORMATION_MESSAGE, getImageFromURL(meme.getUrl()), options.toArray(), options.get(0));
            op = options.indexOf(input);
//abre el meme en el navegador chrome
            if(op == 1) Runtime.getRuntime().exec(new String[]{"cmd", "/c","start chrome "+meme.getPostLink()});
        }while(op != 3);
    }

    private static Icon getImageFromURL(String url) throws IOException, MalformedURLException {
        return new ImageIcon(ImageIO.read(new URL(url)).getScaledInstance(800,800, BufferedImage.SCALE_SMOOTH));
    }

    private static Meme getMemeFromAPI() {
        Unirest.setTimeouts(0, 0);
        Meme meme = new Meme();
        try {
            HttpResponse<String> response = Unirest.get("https://meme-api.herokuapp.com/gimme")
                    .asString();
             meme = new Gson().fromJson(response.getBody(), Meme.class);
        } catch (UnirestException e) {
            e.printStackTrace();
        }
        return meme;
    }
}

Clase Meme

public class Meme {
    private String url;
    private String postLink;
    private String subreddit;
    private String title;
    //private final String apiKey= "";

    public Meme() {}

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getPostLink() {
        return postLink;
    }

    public void setPostLink(String postLink) {
        this.postLink = postLink;
    }

    public String getSubreddit() {
        return subreddit;
    }

    public void setSubreddit(String subreddit) {
        this.subreddit = subreddit;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

No esperen que todo les salga perfecto a la primera, tambien hay que leer los comentarios de los compañeros he ir probando el código por nuestra cuenta y haciendo Debug para entender y identificar los errores en la líneas especificas. antes de implementar el menú hice pruebas, y con el apoyo de los comentarios fui corrigiendo los errores que se tenia. así me quedo la clase GatosService:

<public class GatosService {
    
    public static void verGatos() throws IOException {
        
        // Traemos los datos de la Api dados por postman
        
        OkHttpClient client = new OkHttpClient();
        // MediaType mediaType = MediaType.parse("text/plain");
        // RequestBody body = RequestBody.create(mediaType, "");
        Request request = new Request.Builder()
          .url("https://api.thecatapi.com/v1/images/search")
          .get()
          .build();
        Response response = client.newCall(request).execute();
        
        String elJson = response.body().string(); 
        
        // devemos cortar los primeros corchetes de iteracion del archivo
        elJson = elJson.substring(1, elJson.length()); // corte el primer corteche
        elJson = elJson.substring(0, elJson.length()-1); // corto el ultimo corchete
        
        // creo el objeto de la Gson
        Gson gson = new Gson(); 
        
        // Apartir del gson, creo el objeto gato
        Gatos gatos = gson.fromJson(elJson, Gatos.class); 
        
        // Redimencinar Imagen 
        
        Image image = null;
        
        try {
            URL url = new URL(gatos.getUrl());
            //Creo una conexión HTTP con el servidor que aloja la imagen del perro
            HttpURLConnection http = (HttpURLConnection) url.openConnection();
            // Agrega una propiedad de solicitud al objeto http
            http.addRequestProperty("User-Agent", "");
            BufferedImage bufferedImage = ImageIO.read(http.getInputStream());
            ImageIcon fondoGato = new ImageIcon(bufferedImage); 
            
            if (fondoGato.getIconWidth() > 800 || fondoGato.getIconHeight() > 500) {
                
                // redimencionar
                Image fondo = fondoGato.getImage();
                Image modificada = fondo.getScaledInstance(800, 500, java.awt.Image.SCALE_SMOOTH); 
                fondoGato = new ImageIcon(modificada);
            }

            String id_gato = gatos.getId();
            String opcion = (String) JOptionPane.showInputDialog(null, null, id_gato, JOptionPane.INFORMATION_MESSAGE, fondoGato,null, null);
            
            
        } catch (IOException e) {
            
            System.out.println(e);
        }
    }
    
}> 

Después de luchar porque tenia un error, era cuestión de solo leer la documentación y vi el porque rápido. Logre este producto final.

Salioooooo

Compañeros conseguí la explicación del código que compartieron para los que les causaba el error de la URL.

[Explicacion del objeto HttpUrlConnection] (https://como-programar.net/en-android/httpurlconnection/)

tengo un problema cuando corre el siguiente fragmento de codigo

<URL url = new URL(gatos.getUrl()); image = ImageIO.read(url);>

image viene como null. Probé utilizando openStream() pero me salta error 403.

<image = ImageIO.read(url.openStream());>

java.io.IOException: Server returned HTTP response code: 403 for URL: https://cdn2.thecatapi.com/images/0KUWJZPjy.jpg

A alguien le paso lo mismo? busque, pero todavía no encontré solución.

Hola, para los que les das error al ejecutar deberían copiar exactamente la misma dirección que usa Santiago. A mi solo con esa me funcionó.
Aquí se las dejo: https://api.thecatapi.com/v1/images/search

Cuidado con la versión del okio que utilizan, yo había descargado 2.2.2 y me estaba dando error, cambié a 1.6.0 para que funcionara

Listo, muy bien para algo introductorio, vamos mejorando

Tiene un error grave de llamado recursivo en el método verGato

Super 😃

En caso de que no te abra la documentación en thecatapi debes usar una vpn (en mi caso usé proton vpn), y debes configurar como máximo java 17 (yo como tenía java 21 no me cargaba okhttp en el pom.xml).

Aqui está mi gatito:

Esta clase la tuve que ver dos veces jaja pero muy bueno

Lo estoy haciendo en Intellij y estaba luchando con correrlo porque me salia el error “Can’t get input strea from URL!”.
Finalmente corrio cuando el IDE me llevo a hacer un scratch.java

import java.io.IOException;
class Scratch {
    public static void main(String[] args) throws IOException {
        GatosService.verGatos();
    }
}

y el aporte del codigo de importar la imagen

Image image = null;
        try{
URL url = new URL(gatos.getUrl());
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.addRequestProperty("User-Agent", "");
BufferedImage bufferedImage = ImageIO.read(http.getInputStream());
ImageIcon fondoGato = new ImageIcon(bufferedImage);

if(fondoGato.getIconWidth() > 800) {

Ha cambiado un poco la respuesta de la API desde que se sacó el curso. Aqui mi solucion (si eliminas el break de despues del switch se convierte en un bucle de gatos infinito xD):

package com.cats_api;

import java.awt.Image;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

import com.google.gson.Gson;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

public class CatsService {

	public static void showCats() throws IOException {
		// Crear un cliente HTTP para realizar solicitudes a la API
		OkHttpClient client = new OkHttpClient();

		// Construir la solicitud HTTP GET con la URL de la API y el cuerpo de la
		// solicitud
		Request request = new Request.Builder().url("https://api.thecatapi.com/v1/images/search?limit=10").get()
				.build();

		// Ejecutar la solicitud HTTP y obtener la respuesta
		Response response = client.newCall(request).execute();

		// Extraer la respuesta en formato JSON como String
		String respJSON = response.body().string();

		// Imprimir la respuesta JSON en la consola
		System.out.println(respJSON);

		// Crear un objeto Gson para manejar la serialización/deserialización de JSON
		Gson gson = new Gson();

		// Deserializar la respuesta JSON a un array de objetos Cats
		Cats[] catsArray = gson.fromJson(respJSON, Cats[].class);

		for (Cats cats : catsArray) {

			// Crear una variable para almacenar la imagen
			Image img = null;

			try {
				// Crear un objeto URL a partir de la URL de la imagen en la respuesta JSON
				URL url = new URL(cats.getUrl());

				// Leer la imagen desde la URL
				img = ImageIO.read(url);

				// Crear un ImageIcon con la imagen obtenida
				ImageIcon catBackground = new ImageIcon(img);

				// Si el ancho de la imagen es mayor a 800, redimensionarla
				if (catBackground.getIconWidth() > 800) {
					Image background = catBackground.getImage();
					Image newBackground = background.getScaledInstance(800, 600, java.awt.Image.SCALE_SMOOTH);
					catBackground = new ImageIcon(newBackground);
				}

				String menu = "Opciones:\n" + "1- Ver otra imagen\n" + "2- Favoritos\n" + "3- Volver";

				String[] botones = { "ver otra imagen", "favoritos", "volver" };

				String idCat = cats.getId();

				String opcion = (String) JOptionPane.showInputDialog(null, menu, idCat, JOptionPane.INFORMATION_MESSAGE,
						catBackground, botones, botones[0]);

				int seleccion = -1;

				for (int i = 0; i < botones.length; i++) {
					if (opcion.equals(botones[i])) {
						seleccion = i;
					}
				}

				switch (seleccion) {
				case 0:
					showCats();
					break;
				case 1:
					favoriteCat(cats);
					break;
				case 2:
					break;
				default:
					System.out.println("Opcion no valida");
					break;
				}
				break;

			} catch (Exception e) {
				// Imprimir un mensaje de error si hay algún problema al formatear la imagen
				System.out.println("Error al formatear imagen");
			}
		}
	}

	public static void favoriteCat(Cats cat) {

	}
} 

A mi se me ocurrio la “genial” idea de usar otra api, pense q seria tan facil como cambiar nombres a atributos y demas, pero esta API que usa el profe devuelve un Json simple, pero q pasa cuando recibimos un arreglo de JSON? o cuando uno de los atributos de JSON tiene sub atributos?

Bueno me di a la tarea de investigar mas de Gson y en particular de la funcion fromJson y encontre este articulo q lo explica muy simple , que espera recibir y que espera dar y ademas explica otra funcion muy util toJson.

Pero aun falta la respuesta a la preguna y si la API devuelve un arreglo de Json o si un atributo tiene subatributos y aqui esta el otro articulo que me ayudo, basicamente para los arreglos pues tiene q haber un atributo en tu clase que sea de tipo List o derivado y para los sub atributos pues hay que crear otra clase que los contenga

Espero q esta informacion te sea de utilidad y me disculpo por la ortografia y redaccion, es tarde y me voy a desmayar XD.

este video fue un desastre…!!

Na hasta dejo el curso.
La verdad no entiendo nada. me marca error el codigo no es el mismo y la unica solucion es copiar y pegar pero sin entender que haces mal y que haces bien.
Creo que el back no va a ser para mi, sinceramente hasta 5 videos atras venia super bien pero ya simplemente no entiendo y no creo que sea mi culpa aun que tal vez si.

si les sale el siguiente error:

Exception in thread "main" java.lang.NoClassDefFoundError: okio/Buffer

Eliminen todas las dependencias, y instalen específicamente las mencionadas 2 clases

En caso les salga el error " Failed to invoke public com.platzi.gatos_app.Gatos()" , deben tener un constructor con parámetros en esa Clase.

obtengo esta excepción

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.ssl.Alerts.getSSLException(Alerts.java:198)
	at java.base/sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1969)

Por que en clases anteriores era un misterio la apikey y acá si la muestran?

Se debería o no mantener confidencial?

Estupenda clase instructor Santiago, acá dejo una imagen de como se ve en la que yo estoy realizando:
 
 

se complica la cosa, gracias profe

Estimados… tengo este incoveniente:
javax.imageio.IIOException: Can’t get input stream from URL!

Me sale el error de Can’t get input stream from URL! logre solucionarlo gracias al código que compartieron. Tendre que haberiguar que hace exactamente cada linea de código, porque fue eficaz.

Puedo correrlo en VSC en vez de netBeans?
NetBeans tuve ciertos problemas ya que no me queria agregar la clase dentro del paquete, si no por serparado por eso intento hacerlo por VSC, peroooo no me agarra el llamado de la API.


Luego de mucho tiempo analizando el codigo me salió!! Y asi me quedó

Funciono perfectamente.

Decidí implementar la clase GatosService de la siguiente manera:

public class CatService {

    private static String consultCat() throws IOException{
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://api.thecatapi.com/v1/images/search")
                .method("GET", null)
                .build();
        return client.newCall(request).execute().body().string();
    }

    public static void verGatos() throws IOException {
        String[] menuButtons = {"Ver otra imagen", "Favorito", "Volver"};
        String jsonRequest = consultCat();
        Cat cat = fromJsonRequestToGato(jsonRequest);
        ImageIcon menuIcon = GetAndResizeCatImage (cat);

        int selection = catsMenu(cat, menuIcon, menuButtons);

        switch (selection) {
            case 0:
                verGatos();
                break;
            case 1:
                System.out.println("Hola, soy la opción 2");
                break;
            case 2:
                System.out.println("Hola, soy la opción 3");
                break;
            default:
                System.out.println("Default option");
            break;
        }

    }

    public static int catsMenu(Cat cat, ImageIcon menuIcon, String[] buttons) {

        int selection = -1;
        String menu = "Opciones:\n" + String.join("\n", buttons);
        String idCat = cat.getId();

        String optionSelected = (String) JOptionPane.showInputDialog(
                null,
                menu,
                idCat,
                JOptionPane.INFORMATION_MESSAGE,
                menuIcon,
                buttons,
                buttons[0]);

        for (int i = 0; i < buttons.length; i++) {
            if (optionSelected.equals(buttons[i])) {
                selection = i;
            }
        }
        return selection;
    }

    public static ImageIcon GetAndResizeCatImage (Cat cat) {
        //Redimensionar la imagen en caso de necesitarlo
        Image image = null;
        ImageIcon menuIcon = null;
        try {
            URL url = new URL(cat.getUrl());
            HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
            httpConnection.addRequestProperty("User-agent","");

            image = ImageIO.read(httpConnection.getInputStream());

            menuIcon = new ImageIcon(image);

            if (menuIcon.getIconWidth() > 800) {
                //Redimensionamos la imagen
                Image fondoRedimensionado = menuIcon
                        .getImage()
                        .getScaledInstance(300, 100, Image.SCALE_DEFAULT);

                menuIcon = new ImageIcon(fondoRedimensionado);
            }
        } catch (IOException e) {
            System.out.println("Error al obtener la imagen--> " + e.getMessage());
        }
        return menuIcon;
    }

    public static Cat fromJsonRequestToGato (String jsonRequest) {
        Gson gson = new Gson();
        //Cortar los corchetes de inicio y fin de la petición
        jsonRequest = jsonRequest.substring(1, jsonRequest.length() - 1);
        return gson.fromJson(jsonRequest, Cat.class);
    }

}

Explicación del siguiente código(el cual fue de ayuda en los comentario de la comunidad), para mostrar las imagénes.

new URL(perros.getUrl());
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.addRequestProperty("User-Agent", "");
BufferedImage bufferedImage = ImageIO.read(http.getInputStream());
ImageIcon fondoPerrito = new ImageIcon(bufferedImage);
  • URL url = new URL(perros.getUrl()): Crea un objeto URL a partir de una cadena de texto que representa la dirección URL de una imagen de un perro. Se asume que perros es un objeto que tiene un método getUrl() que devuelve la cadena de texto de la dirección URL.

  • HttpURLConnection http = (HttpURLConnection) url.openConnection(): Crea una conexión HTTP con el servidor que aloja la imagen del perro. La conexión se establece utilizando la URL creada anteriormente. Se utiliza el método openConnection() para crear la conexión y se devuelve un objeto de tipo HttpURLConnection. Es necesario hacer un casting a HttpURLConnection porque el método openConnection() devuelve un objeto de tipo URLConnection, que es la clase padre de HttpURLConnection.

  • http.addRequestProperty(“User-Agent”, “”): Agrega una propiedad de solicitud al objeto http. En este caso, se agrega una propiedad que indica el User-Agent de la solicitud HTTP. El User-Agent es una cadena de texto que identifica el tipo de navegador o aplicación que se está utilizando para realizar la solicitud. En este caso, se establece en una cadena vacía, lo que indica que no se proporciona ninguna información sobre el User-Agent.

  • BufferedImage bufferedImage = ImageIO.read(http.getInputStream()): Lee la imagen del perro desde la entrada de la conexión HTTP y la almacena en un objeto BufferedImage. La clase ImageIO proporciona métodos para leer y escribir imágenes en varios formatos. En este caso, se utiliza el método read() para leer la imagen desde la entrada de la conexión HTTP y almacenarla en un objeto `BufferedImage

Excelente!

Todo bien hasta el momento, no tuve errores.

Para el caso de la imagen, solo se esta controlando el ancho, también debería validarse la altura.
if(fondoGato.getIconWidth() > 800 || fondoGato.getIconHeight()>1200){


}

O todo caso le ponen un tamaño fijo para que todas las imagenes tengan el mismo tamaño.
Image fondoModificado = fondo.getScaledInstance(600, 600, java.awt.Image.SCALE_SMOOTH);

Aquí quiero decir que es una mala práctica de código colocar código dentro de un try, en general una función debe tener sólo una tarea, el try tiene la tarea de únicamente evaluar si se puede hacer algo sin que suceda un error, así que dentro debería ir únicamente lo que activa ese error.