Hacer una solicitud HTTP con Android

Respuestas:

477

ACTUALIZAR

Esta es una respuesta muy antigua. Definitivamente ya no recomendaré el cliente de Apache. En su lugar use cualquiera:

Respuesta original

En primer lugar, solicite un permiso para acceder a la red, agregue lo siguiente a su manifiesto:

<uses-permission android:name="android.permission.INTERNET" />

Entonces, la forma más fácil es usar el cliente http Apache incluido con Android:

    HttpClient httpclient = new DefaultHttpClient();
    HttpResponse response = httpclient.execute(new HttpGet(URL));
    StatusLine statusLine = response.getStatusLine();
    if(statusLine.getStatusCode() == HttpStatus.SC_OK){
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        response.getEntity().writeTo(out);
        String responseString = out.toString();
        out.close();
        //..more logic
    } else{
        //Closes the connection.
        response.getEntity().getContent().close();
        throw new IOException(statusLine.getReasonPhrase());
    }

Si desea que se ejecute en un hilo separado, le recomiendo extender AsyncTask:

class RequestTask extends AsyncTask<String, String, String>{

    @Override
    protected String doInBackground(String... uri) {
        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response;
        String responseString = null;
        try {
            response = httpclient.execute(new HttpGet(uri[0]));
            StatusLine statusLine = response.getStatusLine();
            if(statusLine.getStatusCode() == HttpStatus.SC_OK){
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                responseString = out.toString();
                out.close();
            } else{
                //Closes the connection.
                response.getEntity().getContent().close();
                throw new IOException(statusLine.getReasonPhrase());
            }
        } catch (ClientProtocolException e) {
            //TODO Handle problems..
        } catch (IOException e) {
            //TODO Handle problems..
        }
        return responseString;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        //Do anything with response..
    }
}

Luego puede hacer una solicitud:

   new RequestTask().execute("http://stackoverflow.com");
Konstantin Burov
fuente
11
Aquí hay un artículo del blog oficial de desarrolladores de Android en AsyncTask: android-developers.blogspot.com/2010/07/…
Austyn Mahoney
77
para pan de jengibre o superior, se recomienda usar HttpURLConnection sobre la biblioteca apache, consulte android-developers.blogspot.com/2011/09/… . Es menos exigente con la batería y tiene un mejor rendimiento
Marty
8
responseString = out.toString () debe estar antes de la llamada out.close (). En realidad, probablemente debería tener el out.close () en un bloque finalmente. Pero en general, una respuesta muy útil (+1), ¡gracias!
dcp
99
A partir de Honeycomb (SDK 11), el enfoque asíncrono es el camino a seguir. Se genera una excepción NetworkOnMainThreadException cuando intenta ejecutar una solicitud HTTP desde el hilo principal.
msrxthr
2
Esta respuesta es bastante excelente. Pero yo recomendaría no usar AsyncTasks para Networking. Pueden crear pérdidas de memoria muy fácilmente (y en realidad el ejemplo proporcionado sí pierde), y no proporcionan todas las características que uno puede esperar para las solicitudes de red. Considere usar RoboSpice para este tipo de tareas en segundo plano: github.com/octo-online/robospice
Snicolas
67

a menos que tenga una razón explícita para elegir el HttpClient de Apache, debería preferir java.net.URLConnection. puedes encontrar muchos ejemplos de cómo usarlo en la web.

También hemos mejorado la documentación de Android desde su publicación original: http://developer.android.com/reference/java/net/HttpURLConnection.html

y hemos hablado sobre las compensaciones en el blog oficial: http://android-developers.blogspot.com/2011/09/androids-http-clients.html

Elliott Hughes
fuente
13
¿Por qué no se recomienda usar Apache HttpClient?
Ted
44
Un co-conspirador mío entró en esto con gran detalle en el blog oficial: android-developers.blogspot.com/2011/09/…
Elliott Hughes
@ElliottHughes: estoy de acuerdo al 100%. No se puede negar que el httpclient de Apache ofrece métodos fáciles y una vista más abstracta del protocolo, pero la conexión url nativa de Java no es de ninguna manera menos útil. Con un poco de práctica, es tan fácil de usar como httpclient, y es mucho más portátil
Nitin Bansal
1
En realidad, si echas un vistazo al video Google I / O 2010 - Aplicaciones cliente REST de Android ( youtube.com/watch?v=xHXn3Kg2IQE 57min21sec), verías que Apache HttpClient es el más recomendado. Cito a Virgil Dobjanschi (un ingeniero de software en Google que trabaja en el grupo de aplicaciones de Android) "Simplemente le aconsejaría que use el cliente HTTP Apache, porque tiene una implementación más sólida. El tipo de conexión URL de la transacción HTTP no es la más eficiente implementación. Y la forma en que termina las conexiones a veces puede tener un efecto adverso en la red ".
Alan
46

Nota: El cliente HTTP Apache incluido con Android ahora está en desuso a favor de HttpURLConnection . Consulte el Blog de desarrolladores de Android para obtener más detalles.

Agregue <uses-permission android:name="android.permission.INTERNET" />a su manifiesto.

Luego recuperarías una página web de esta manera:

URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
     readStream(in);
}
finally {
     urlConnection.disconnect();
}

También sugiero ejecutarlo en un hilo separado:

class RequestTask extends AsyncTask<String, String, String>{

@Override
protected String doInBackground(String... uri) {
    String responseString = null;
    try {
        URL url = new URL(myurl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        if(conn.getResponseCode() == HttpsURLConnection.HTTP_OK){
            // Do normal input or output stream reading
        }
        else {
            response = "FAILED"; // See documentation for more info on response handling
        }
    } catch (ClientProtocolException e) {
        //TODO Handle problems..
    } catch (IOException e) {
        //TODO Handle problems..
    }
    return responseString;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    //Do anything with response..
}
}

Consulte la documentación para obtener más información sobre el manejo de respuestas y las solicitudes POST.

kevinc
fuente
1
@Semmix ¿Cómo es eso? La pregunta pedía una solicitud "HTTP simple", y mi código hace exactamente eso.
kevinc el
1
Entiendo que su primer bloque de código es una copia pegada de los documentos de Android, pero el hombre es esa basura de muestra / documento. readStreamNi siquiera está definido.
Eugene K
@EugeneK Lo son, pero esta es probablemente la forma más sencilla de responder a esta pregunta. Hacer una solicitud HTTP correctamente en Android implicaría explicar Retrofit y OkHttp. Creo que eso confundiría a los principiantes más que simplemente entregar un fragmento que técnicamente hará una simple solicitud HTTP, incluso si está mal construida.
kevinc
12

La forma más simple es usar la lib de Android llamada Volley

Volley ofrece los siguientes beneficios:

Programación automática de solicitudes de red. Múltiples conexiones de red concurrentes . Disco transparente y memoria caché de respuesta con coherencia de caché HTTP estándar. Soporte para solicitud de priorización. Solicitud de cancelación API. Puede cancelar una sola solicitud o puede establecer bloques o ámbitos de solicitudes para cancelar. Facilidad de personalización, por ejemplo, para reintentos y retrocesos. Ordenación sólida que facilita el llenado correcto de la interfaz de usuario con datos obtenidos de forma asincrónica de la red. Herramientas de depuración y rastreo.

Puede enviar una solicitud http / https tan simple como esto:

        // Instantiate the RequestQueue.
        RequestQueue queue = Volley.newRequestQueue(this);
        String url ="http://www.yourapi.com";
        JsonObjectRequest request = new JsonObjectRequest(url, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    if (null != response) {
                         try {
                             //handle your response
                         } catch (JSONException e) {
                             e.printStackTrace();
                         }
                    }
                }
            }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        queue.add(request);

En este caso, no es necesario que consideres "ejecutar en segundo plano" o "usar caché", ya que Volley ya ha hecho todo esto.

Shao Wenbin
fuente
6
private String getToServer(String service) throws IOException {
    HttpGet httpget = new HttpGet(service);
    ResponseHandler<String> responseHandler = new BasicResponseHandler();
    return new DefaultHttpClient().execute(httpget, responseHandler);

}

Saludos

Gabriel Gómez
fuente
4

Con un hilo:

private class LoadingThread extends Thread {
    Handler handler;

    LoadingThread(Handler h) {
        handler = h;
    }
    @Override
    public void run() {
        Message m = handler.obtainMessage();
        try {
            BufferedReader in = 
                new BufferedReader(new InputStreamReader(url.openStream()));
            String page = "";
            String inLine;

            while ((inLine = in.readLine()) != null) {
                page += inLine;
            }

            in.close();
            Bundle b = new Bundle();
            b.putString("result", page);
            m.setData(b);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        handler.sendMessage(m);
    }
}
Fredley
fuente
4

Hice esto para un servicio web para solicitar URL, usando una lib Gson:

Cliente:

public EstabelecimentoList getListaEstabelecimentoPorPromocao(){

        EstabelecimentoList estabelecimentoList  = new EstabelecimentoList();
        try{
            URL url = new URL("http://" +  Conexao.getSERVIDOR()+ "/cardapio.online/rest/recursos/busca_estabelecimento_promocao_android");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();

            if (con.getResponseCode() != 200) {
                    throw new RuntimeException("HTTP error code : "+ con.getResponseCode());
            }

            BufferedReader br = new BufferedReader(new InputStreamReader((con.getInputStream())));
            estabelecimentoList = new Gson().fromJson(br, EstabelecimentoList.class);
            con.disconnect();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return estabelecimentoList;
}
Deividson Calixto
fuente
4

Mira esta nueva biblioteca increíble que está disponible a través de gradle :)

build.gradle: compile 'com.apptakk.http_request:http-request:0.1.2'

Uso:

new HttpRequestTask(
    new HttpRequest("http://httpbin.org/post", HttpRequest.POST, "{ \"some\": \"data\" }"),
    new HttpRequest.Handler() {
      @Override
      public void response(HttpResponse response) {
        if (response.code == 200) {
          Log.d(this.getClass().toString(), "Request successful!");
        } else {
          Log.e(this.getClass().toString(), "Request unsuccessful: " + response);
        }
      }
    }).execute();

https://github.com/erf/http-request

electronix384128
fuente
1
Parece como cualquier otra biblioteca ...
Nick Gallimore
3

Use Volley como se sugirió anteriormente. Agregue lo siguiente en build.gradle (Módulo: aplicación)

implementation 'com.android.volley:volley:1.1.1'

Agregue lo siguiente en AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

Y agregue el siguiente código de actividad:

public void httpCall(String url) {

    RequestQueue queue = Volley.newRequestQueue(this);

    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // enjoy your response
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    // enjoy your error status
                }
    });

    queue.add(stringRequest);
}

Reemplaza al cliente http y es muy simple.

Jarda Pavlíček
fuente
2

Este es el nuevo código para la solicitud HTTP Get / POST en Android. HTTPClientestá depurada y puede no estar disponible como estaba en mi caso.

Primero agregue las dos dependencias en build.gradle:

compile 'org.apache.httpcomponents:httpcore:4.4.1'
compile 'org.apache.httpcomponents:httpclient:4.5'

Luego escriba este código ASyncTasken el doBackgroundmétodo.

 URL url = new URL("http://localhost:8080/web/get?key=value");
 HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
 urlConnection.setRequestMethod("GET");
 int statusCode = urlConnection.getResponseCode();
 if (statusCode ==  200) {
      InputStream it = new BufferedInputStream(urlConnection.getInputStream());
      InputStreamReader read = new InputStreamReader(it);
      BufferedReader buff = new BufferedReader(read);
      StringBuilder dta = new StringBuilder();
      String chunks ;
      while((chunks = buff.readLine()) != null)
      {
         dta.append(chunks);
      }
 }
 else
 {
     //Handle else
 }
Rahul Raina
fuente
El código puede quedar obsoleto y apache ya no es compatible con la plataforma 28 de la plataforma Android. En ese caso, puede habilitar la propiedad heredada de apache en el archivo Gradle de nivel de módulo o de manifiesto. Sin embargo, se recomienda utilizar la biblioteca de red OKHttp, Volley o Retrofit.
Rahul Raina
1

Para mí, la forma más fácil es usar una biblioteca llamada Retrofit2

Solo necesitamos crear una interfaz que contenga nuestro método de solicitud, parámetros, y también podemos hacer un encabezado personalizado para cada solicitud:

    public interface MyService {

      @GET("users/{user}/repos")
      Call<List<Repo>> listRepos(@Path("user") String user);

      @GET("user")
      Call<UserDetails> getUserDetails(@Header("Authorization") String   credentials);

      @POST("users/new")
      Call<User> createUser(@Body User user);

      @FormUrlEncoded
      @POST("user/edit")
      Call<User> updateUser(@Field("first_name") String first, 
                            @Field("last_name") String last);

      @Multipart
      @PUT("user/photo")
      Call<User> updateUser(@Part("photo") RequestBody photo, 
                            @Part("description") RequestBody description);

      @Headers({
        "Accept: application/vnd.github.v3.full+json",
        "User-Agent: Retrofit-Sample-App"
      })
      @GET("users/{username}")
      Call<User> getUser(@Path("username") String username);    

    }

Y lo mejor es que podemos hacerlo de forma asincrónica fácilmente utilizando el método en cola

faruk
fuente
1

Como ninguna de las respuestas describe una forma de realizar solicitudes con OkHttp , que es un cliente http muy popular actualmente para Android y Java en general, voy a proporcionar un ejemplo simple:

//get an instance of the client
OkHttpClient client = new OkHttpClient();

//add parameters
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://www.example.com").newBuilder();
urlBuilder.addQueryParameter("query", "stack-overflow");


String url = urlBuilder.build().toString();

//build the request
Request request = new Request.Builder().url(url).build();

//execute
Response response = client.newCall(request).execute();

La clara ventaja de esta biblioteca es que nos abstrae de algunos detalles de bajo nivel, proporcionando formas más amigables y seguras de interactuar con ellos. La sintaxis también se simplifica y permite escribir código agradable.

NiVeR
fuente