Comment envoyer une requête POST en JSON en utilisant HTTPClient sous Android?

111

J'essaie de comprendre comment POST JSON à partir d'Android en utilisant HTTPClient. J'essaie de comprendre cela depuis un certain temps, j'ai trouvé de nombreux exemples en ligne, mais je ne peux faire fonctionner aucun d'entre eux. Je pense que cela est dû à mon manque de connaissances JSON / réseau en général. Je sais qu'il existe de nombreux exemples, mais quelqu'un pourrait-il m'indiquer un tutoriel réel? Je recherche un processus étape par étape avec du code et une explication de la raison pour laquelle vous faites chaque étape ou de ce que fait cette étape. Cela n'a pas besoin d'être compliqué, simple suffira.

Encore une fois, je sais qu'il existe une tonne d'exemples, je cherche simplement un exemple avec une explication de ce qui se passe exactement et pourquoi cela se passe de cette façon.

Si quelqu'un connaît un bon livre Android à ce sujet, faites-le moi savoir.

Merci encore pour l'aide @terrance, voici le code que j'ai décrit ci-dessous

public void shNameVerParams() throws Exception{
     String path = //removed
     HashMap  params = new HashMap();

     params.put(new String("Name"), "Value"); 
     params.put(new String("Name"), "Value");

     try {
        HttpClient.SendHttpPost(path, params);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 }
Gaurav Gandhi
la source
Peut-être pouvez-vous publier l'un des exemples que vous ne pouvez pas mettre en œuvre? En faisant fonctionner quelque chose, vous apprendrez comment les pièces s'emboîtent.
fredw le

Réponses:

157

Dans cette réponse, j'utilise un exemple posté par Justin Grammens .

À propos de JSON

JSON signifie JavaScript Object Notation. Dans JavaScript, les propriétés peuvent être référencées à la fois comme ceci object1.nameet comme ceci object['name'];. L'exemple de l'article utilise ce bit de JSON.

L'
objet de fan Parts A avec email comme clé et [email protected] comme valeur

{
  fan:
    {
      email : '[email protected]'
    }
}

Ainsi, l'équivalent d'objet serait fan.email;ou fan['email'];. Les deux auraient la même valeur de '[email protected]'.

À propos de la demande HttpClient

Ce qui suit est ce que notre auteur a utilisé pour faire une requête HttpClient . Je ne prétends pas du tout être un expert, donc si quelqu'un a une meilleure façon de formuler une partie de la terminologie, n'hésitez pas.

public static HttpResponse makeRequest(String path, Map params) throws Exception 
{
    //instantiates httpclient to make request
    DefaultHttpClient httpclient = new DefaultHttpClient();

    //url with the post data
    HttpPost httpost = new HttpPost(path);

    //convert parameters into JSON object
    JSONObject holder = getJsonObjectFromMap(params);

    //passes the results to a string builder/entity
    StringEntity se = new StringEntity(holder.toString());

    //sets the post request as the resulting string
    httpost.setEntity(se);
    //sets a request header so the page receving the request
    //will know what to do with it
    httpost.setHeader("Accept", "application/json");
    httpost.setHeader("Content-type", "application/json");

    //Handles what is returned from the page 
    ResponseHandler responseHandler = new BasicResponseHandler();
    return httpclient.execute(httpost, responseHandler);
}

Carte

Si vous n'êtes pas familier avec la Mapstructure des données, veuillez consulter la référence Java Map . En bref, une carte est similaire à un dictionnaire ou à un hachage.

private static JSONObject getJsonObjectFromMap(Map params) throws JSONException {

    //all the passed parameters from the post request
    //iterator used to loop through all the parameters
    //passed in the post request
    Iterator iter = params.entrySet().iterator();

    //Stores JSON
    JSONObject holder = new JSONObject();

    //using the earlier example your first entry would get email
    //and the inner while would get the value which would be '[email protected]' 
    //{ fan: { email : '[email protected]' } }

    //While there is another entry
    while (iter.hasNext()) 
    {
        //gets an entry in the params
        Map.Entry pairs = (Map.Entry)iter.next();

        //creates a key for Map
        String key = (String)pairs.getKey();

        //Create a new map
        Map m = (Map)pairs.getValue();   

        //object for storing Json
        JSONObject data = new JSONObject();

        //gets the value
        Iterator iter2 = m.entrySet().iterator();
        while (iter2.hasNext()) 
        {
            Map.Entry pairs2 = (Map.Entry)iter2.next();
            data.put((String)pairs2.getKey(), (String)pairs2.getValue());
        }

        //puts email and '[email protected]'  together in map
        holder.put(key, data);
    }
    return holder;
}

N'hésitez pas à commenter toutes les questions qui se posent à propos de cet article ou si je n'ai pas précisé quelque chose ou si je n'ai pas abordé quelque chose qui vous trouble encore ... etc tout ce qui vous vient vraiment à l'esprit.

(Je décrocherai si Justin Grammens n'approuve pas. Mais sinon, merci à Justin d'être cool à ce sujet.)

Mettre à jour

J'ai juste eu l'occasion d'obtenir un commentaire sur la façon d'utiliser le code et j'ai réalisé qu'il y avait une erreur dans le type de retour. La signature de la méthode a été définie pour renvoyer une chaîne mais dans ce cas, elle ne retournait rien. J'ai changé la signature en HttpResponse et je vous renverrai à ce lien sur Obtenir le corps de réponse de HttpResponse la variable de chemin est l'url et j'ai mis à jour pour corriger une erreur dans le code.

Terrance
la source
Merci @Terrance. Donc, dans une classe différente, il crée une carte qui a différentes clés et valeurs qui seront ensuite transformées en JSONObjects. J'ai essayé d'implémenter quelque chose de similaire, mais je n'ai aucune expérience avec les cartes non plus, j'ajouterai le code de ce que j'ai essayé d'implémenter à mon message d'origine. Vos explications sur ce qui s'est passé depuis, et j'ai réussi à le faire fonctionner en créant des JSONObjects avec des noms et des valeurs codés en dur. Merci!
Woot, content de pouvoir aider.
Terrance
Justin dit qu'il approuve. Il devrait avoir suffisamment de représentants pour venir et laisser un commentaire lui-même maintenant.
Abizern
Je veux utiliser ce code. Comment dois-je procéder? Veuillez spécifier quelle est la variable de chemin et ce qui doit être retourné afin que, à ma fin Java, je puisse récupérer les données.
Prateek
3
Il n'y a aucune raison pour getJsonObjectFromMap(): JSONObject a un constructeur qui prend un Map: developer.android.com/reference/org/json/…
pr1001
41

Voici une solution alternative à la réponse de @ Terrance. Vous pouvez facilement externaliser la conversion. La bibliothèque Gson fait un travail remarquable en convertissant diverses structures de données en JSON et inversement .

public static void execute() {
    Map<String, String> comment = new HashMap<String, String>();
    comment.put("subject", "Using the GSON library");
    comment.put("message", "Using libraries is convenient.");
    String json = new GsonBuilder().create().toJson(comment, Map.class);
    makeRequest("http://192.168.0.1:3000/post/77/comments", json);
}

public static HttpResponse makeRequest(String uri, String json) {
    try {
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setEntity(new StringEntity(json));
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");
        return new DefaultHttpClient().execute(httpPost);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Similaire peut être fait en utilisant Jackson au lieu de Gson. Je recommande également de jeter un œil à Retrofit qui cache une grande partie de ce code passe-partout pour vous. Pour les développeurs plus expérimentés, je recommande d'essayer RxAndroid .

JJD
la source
mon application envoie des données via la méthode HttpPut.Lorsque le serveur reçoit une demande, il répond en tant que données json. Je ne sais pas comment obtenir des données de json. s'il vous plaît dites-moi. CODE .
kongkea
@kongkea Veuillez jeter un œil à la bibliothèque GSON . Il est capable d'analyser le fichier JSON en objets Java.
JJD
@JJD Jusqu'à présent, ce que vous suggérez est d'envoyer des données au serveur distant et c'est une belle explication, mais vous voulez savoir comment analyser l'objet JSON en utilisant le protocole HTTP. Pouvez-vous élaborer votre réponse avec l'analyse JSON également. Ce sera très utile pour tous ceux qui sont nouveaux dans ce domaine.
AndroidDev
@AndroidDev Veuillez ouvrir une nouvelle question car cette question concerne l'envoi de données du client au serveur. N'hésitez pas à déposer un lien ici.
JJD
@JJD vous appelez la méthode abstraite execute()et elle échoue bien sûr
Konstantin Konopko
33

Je recommande d'utiliser ceci à la HttpURLConnectionplace HttpGet. Tel qu'il HttpGetest déjà obsolète dans l'API Android niveau 22.

HttpURLConnection httpcon;  
String url = null;
String data = null;
String result = null;
try {
  //Connect
  httpcon = (HttpURLConnection) ((new URL (url).openConnection()));
  httpcon.setDoOutput(true);
  httpcon.setRequestProperty("Content-Type", "application/json");
  httpcon.setRequestProperty("Accept", "application/json");
  httpcon.setRequestMethod("POST");
  httpcon.connect();

  //Write       
  OutputStream os = httpcon.getOutputStream();
  BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
  writer.write(data);
  writer.close();
  os.close();

  //Read        
  BufferedReader br = new BufferedReader(new InputStreamReader(httpcon.getInputStream(),"UTF-8"));

  String line = null; 
  StringBuilder sb = new StringBuilder();         

  while ((line = br.readLine()) != null) {  
    sb.append(line); 
  }         

  br.close();  
  result = sb.toString();

} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} 
Égide
la source
5

Trop de code pour cette tâche, consultez cette bibliothèque https://github.com/kodart/Httpzoid Is utilise GSON en interne et fournit une API qui fonctionne avec des objets. Tous les détails JSON sont masqués.

Http http = HttpFactory.create(context);
http.get("http://example.com/users")
    .handler(new ResponseHandler<User[]>() {
        @Override
        public void success(User[] users, HttpResponse response) {
        }
    }).execute();
Arthur
la source
excellente solution, malheureusement ce plugin manque de support gradle: /
electronix384128
3

Il existe deux façons d'établir une connexion HHTP et d'extraire des données à partir d'un service Web RESTFULL. Le plus récent est GSON. Mais avant de passer à GSON, vous devez avoir une idée de la manière la plus traditionnelle de créer un client HTTP et d'effectuer une communication de données avec un serveur distant. J'ai mentionné les deux méthodes pour envoyer des requêtes POST & GET en utilisant HTTPClient.

/**
 * This method is used to process GET requests to the server.
 * 
 * @param url 
 * @return String
 * @throws IOException
 */
public static String connect(String url) throws IOException {

    HttpGet httpget = new HttpGet(url);
    HttpResponse response;
    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    // The default value is zero, that means the timeout is not used. 
    int timeoutConnection = 60*1000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // Set the default socket timeout (SO_TIMEOUT) 
    // in milliseconds which is the timeout for waiting for data.
    int timeoutSocket = 60*1000;

    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
    HttpClient httpclient = new DefaultHttpClient(httpParameters);
    try {

        response = httpclient.execute(httpget);

        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();
            result = convertStreamToString(instream);
            //instream.close();
        }
    } 
    catch (ClientProtocolException e) {
        Utilities.showDLog("connect","ClientProtocolException:-"+e);
    } catch (IOException e) {
        Utilities.showDLog("connect","IOException:-"+e); 
    }
    return result;
}


 /**
 * This method is used to send POST requests to the server.
 * 
 * @param URL
 * @param paramenter
 * @return result of server response
 */
static public String postHTPPRequest(String URL, String paramenter) {       

    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    // The default value is zero, that means the timeout is not used. 
    int timeoutConnection = 60*1000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // Set the default socket timeout (SO_TIMEOUT) 
    // in milliseconds which is the timeout for waiting for data.
    int timeoutSocket = 60*1000;

    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
    HttpClient httpclient = new DefaultHttpClient(httpParameters);
    HttpPost httppost = new HttpPost(URL);
    httppost.setHeader("Content-Type", "application/json");
    try {
        if (paramenter != null) {
            StringEntity tmp = null;
            tmp = new StringEntity(paramenter, "UTF-8");
            httppost.setEntity(tmp);
        }
        HttpResponse httpResponse = null;
        httpResponse = httpclient.execute(httppost);
        HttpEntity entity = httpResponse.getEntity();
        if (entity != null) {
            InputStream input = null;
            input = entity.getContent();
            String res = convertStreamToString(input);
            return res;
        }
    } 
     catch (Exception e) {
        System.out.print(e.toString());
    }
    return null;
}
Mike Clark
la source