Hacer una solicitud HTTP con Android


352

He buscado en todas partes pero no pude encontrar mi respuesta, ¿hay alguna manera de hacer una solicitud HTTP simple? Quiero solicitar una página / script PHP en uno de mis sitios web, pero no quiero mostrar la página web.

Si es posible, incluso quiero hacerlo en segundo plano (en un BroadcastReceiver)


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");

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


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.


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.


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


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);
    }
}

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;
}

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


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.


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
 }

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


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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.