Faire une requête HTTP avec Android

352

J'ai cherché partout mais je n'ai pas trouvé ma réponse, existe-t-il un moyen de faire une simple requête HTTP? Je souhaite demander une page / un script PHP sur l'un de mes sites Web, mais je ne souhaite pas afficher la page Web.

Si possible, je veux même le faire en arrière-plan (dans un BroadcastReceiver)

Mats Hofman
la source

Réponses:

477

MISE À JOUR

Ceci est une réponse très ancienne. Je ne recommanderai certainement plus le client d'Apache. Utilisez plutôt:

Réponse originale

Tout d'abord, demandez une autorisation d'accès au réseau, ajoutez ce qui suit à votre manifeste:

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

Ensuite, le moyen le plus simple consiste à utiliser le client Apache http fourni avec 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 vous voulez qu'il s'exécute sur un thread séparé, je vous recommande d'étendre 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..
    }
}

Vous pouvez alors faire une demande en:

   new RequestTask().execute("http://stackoverflow.com");
Konstantin Burov
la source
11
Voici un article du blog officiel des développeurs Android sur AsyncTask: android-developers.blogspot.com/2010/07/…
Austyn Mahoney
77
pour du pain d'épices ou plus, il est effectivement conseillé d'utiliser HttpURLConnection sur la bibliothèque apache, voir android-developers.blogspot.com/2011/09/… . Son moins taxant la batterie et a de meilleures performances
Marty
8
responseString = out.toString () doit être avant l'appel out.close (). En fait, vous devriez probablement avoir out.close () dans un bloc finally. Mais dans l'ensemble, réponse très utile (+1), merci!
dcp
9
À partir de Honeycomb (SDK 11), l'approche asynchrone est la voie à suivre. Une exception NetworkOnMainThreadException est levée lorsque vous essayez d'exécuter une demande HTTP à partir du thread principal.
msrxthr
2
Cette réponse est assez excellente. Mais je conseillerais de ne pas utiliser AsyncTasks pour la mise en réseau. Ils peuvent créer des fuites de mémoire très facilement (et en fait l'exemple fourni fuit), et ne fournissent pas toutes les fonctionnalités auxquelles on peut s'attendre pour les requêtes réseau. Pensez à utiliser RoboSpice pour ce type de tâches en arrière-plan: github.com/octo-online/robospice
Snicolas
67

sauf si vous avez une raison explicite de choisir Apache HttpClient, vous devez préférer java.net.URLConnection. vous pouvez trouver de nombreux exemples d'utilisation sur le Web.

nous avons également amélioré la documentation Android depuis votre publication d'origine: http://developer.android.com/reference/java/net/HttpURLConnection.html

et nous avons parlé des compromis sur le blog officiel: http://android-developers.blogspot.com/2011/09/androids-http-clients.html

Elliott Hughes
la source
13
Pourquoi l'utilisation d'Apache HttpClient n'est-elle pas recommandée?
Ted
4
Un de mes co-conspirateurs est entré dans les détails sur le blog officiel: android-developers.blogspot.com/2011/09/…
Elliott Hughes
@ElliottHughes: Je suis d'accord à 100%. Il est indéniable qu'Apache httpclient propose des méthodes simples et une vue plus abstraite du protocole, mais la connexion url native de Java n'est en aucun cas moins utile. Avec un peu de pratique, il est aussi facile à utiliser que httpclient et est beaucoup plus portable
Nitin Bansal
1
En fait, si vous jetez un œil à la vidéo Google I / O 2010 - Applications clientes Android REST ( youtube.com/watch?v=xHXn3Kg2IQE 57min21sec), vous verrez que Apache HttpClient est la plus recommandée. Je cite Virgil Dobjanschi (un ingénieur logiciel sur Google qui travaille sur Android Application Group) "Je vous conseillerais simplement d'utiliser le client HTTP Apache, car il a une implémentation plus robuste. Le type de connexion URL de la transaction HTTP n'est pas le plus efficace La façon dont il met fin aux connexions peut parfois avoir un effet négatif sur le réseau. "
Alan
46

Remarque: Le client HTTP Apache fourni avec Android est désormais déconseillé au profit de HttpURLConnection . Veuillez consulter le blog des développeurs Android pour plus de détails.

Ajoutez <uses-permission android:name="android.permission.INTERNET" />à votre manifeste.

Vous récupéreriez alors une page Web comme ceci:

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

Je suggère également de l'exécuter sur un thread séparé:

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

Consultez la documentation pour plus d'informations sur la gestion des réponses et les requêtes POST.

kevinc
la source
1
@Semmix Comment ça? La question demandait "une simple requête HTTP", et mon code fait exactement cela.
Kevin
1
J'obtiens que votre premier bloc de code est copié collé à partir de documents Android, mais l'homme est cet exemple / doc poubelle. readStreamn'est même pas défini.
Eugene K
@EugeneK Ils le sont, mais c'est probablement le moyen le plus simple de répondre à cette question. Faire une demande HTTP correctement dans Android impliquerait d'expliquer Retrofit et OkHttp. Je pense que cela dérouterait les débutants plus que la simple distribution d'un extrait de code qui fera techniquement une simple requête HTTP, même s'il est mal construit.
Kevin
12

Le moyen le plus simple consiste à utiliser la bibliothèque Android appelée Volley

Volley offre les avantages suivants:

Planification automatique des requêtes réseau. Plusieurs connexions réseau simultanées . Mise en cache transparente des réponses du disque et de la mémoire avec cohérence de cache HTTP standard. Prise en charge de la priorisation des demandes. API de demande d'annulation. Vous pouvez annuler une seule demande ou définir des blocs ou des étendues de demandes à annuler. Facilité de personnalisation, par exemple, pour une nouvelle tentative et une interruption. Ordre solide qui permet de remplir correctement votre interface utilisateur avec des données extraites de manière asynchrone du réseau. Outils de débogage et de traçage.

Vous pouvez envoyer une demande http / https aussi simple que cela:

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

Dans ce cas, vous n'avez pas besoin d'envisager "de fonctionner en arrière-plan" ou "d'utiliser le cache" vous-même car tout cela a déjà été fait par Volley.

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

}

Cordialement

Gabriel Gómez
la source
4

Avec un fil:

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
la source
4

J'ai fait ceci pour qu'un webservice demande sur URL, en utilisant une lib Gson:

Client:

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
la source
4

Regardez cette nouvelle bibliothèque impressionnante qui est disponible via gradle :)

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

Usage:

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
la source
1
On dirait que toutes les autres bibliothèques ...
Nick Gallimore
3

Utilisez Volley comme suggéré ci-dessus. Ajouter le suivant dans build.gradle (Module: app)

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

Ajoutez ce qui suit dans AndroidManifest.xml:

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

Et ajoutez le code d'activité suivant:

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

Il remplace le client http et c'est très simple.

Jarda Pavlíček
la source
2

Il s'agit du nouveau code pour la requête HTTP Get / POST dans Android. HTTPClientest obsolète et peut ne pas être disponible comme c'était le cas dans mon cas.

Ajoutez d'abord les deux dépendances dans build.gradle:

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

Ensuite, écrivez ce code ASyncTaskdans la doBackgroundméthode in .

 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
la source
Le code peut devenir obsolète et apache n'est plus pris en charge dans l'API Android Platform 28. Dans ce cas, vous pouvez activer la propriété héritée apache dans le fichier Gradle au niveau du manifeste ou du module. Cependant, il est recommandé d'utiliser la bibliothèque de mise en réseau OKHttp, Volley ou Retrofit.
Rahul Raina
1

Pour moi, la façon la plus simple est d'utiliser une bibliothèque appelée Retrofit2

Nous avons juste besoin de créer une interface qui contient notre méthode de demande, nos paramètres, et nous pouvons également créer un en-tête personnalisé pour chaque demande:

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

    }

Et le mieux est que nous pouvons le faire de manière asynchrone facilement en utilisant la méthode de mise en file d'attente

faruk
la source
1

Comme aucune des réponses ne décrit un moyen d'effectuer des requêtes avec OkHttp , qui est un client http très populaire de nos jours pour Android et Java en général, je vais fournir un exemple 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();

L'avantage évident de cette bibliothèque est qu'elle nous soustrait à certains détails de bas niveau, offrant des moyens plus conviviaux et sécurisés d'interagir avec eux. La syntaxe est également simplifiée et permet d'écrire du bon code.

NiVeR
la source