Wie sende ich eine POST-Anfrage in JSON mit HTTPClient in Android?

111

Ich versuche herauszufinden, wie man JSON von Android mithilfe von HTTPClient POST. Ich habe eine Weile versucht, dies herauszufinden. Ich habe online viele Beispiele gefunden, aber ich kann keines davon zum Laufen bringen. Ich glaube, das liegt an meinem Mangel an JSON- / Netzwerkkenntnissen im Allgemeinen. Ich weiß, dass es viele Beispiele gibt, aber könnte mich jemand auf ein aktuelles Tutorial verweisen? Ich suche nach einem schrittweisen Prozess mit Code und einer Erklärung, warum Sie jeden Schritt ausführen oder was dieser Schritt bewirkt. Es muss kein komplizierter, einfacher Wille sein.

Wiederum weiß ich, dass es eine Menge Beispiele gibt. Ich suche nur nach einem Beispiel mit einer Erklärung, was genau passiert und warum es so läuft.

Wenn jemand etwas über ein gutes Android-Buch darüber weiß, dann lass es mich wissen.

Nochmals vielen Dank für die Hilfe @terrance, hier ist der Code, den ich unten beschrieben habe

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
quelle
Vielleicht können Sie eines der Beispiele posten, bei denen Sie nicht arbeiten können? Wenn Sie etwas zum Laufen bringen, lernen Sie, wie die Teile zusammenpassen.
Fredw

Antworten:

157

In dieser Antwort verwende ich ein Beispiel von Justin Grammens .

Über JSON

JSON steht für JavaScript Object Notation. In JavaScript - Eigenschaften können beide wie folgt referenziert werden object1.nameund wie diese object['name'];. Das Beispiel aus dem Artikel verwendet dieses JSON-Bit.

Die Teile
Ein Fanobjekt mit E-Mail als Schlüssel und [email protected] als Wert

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

Das Objektäquivalent wäre also fan.email;oder fan['email'];. Beide hätten den gleichen Wert von '[email protected]'.

Informationen zur HttpClient-Anforderung

Das Folgende hat unser Autor verwendet, um eine HttpClient-Anfrage zu stellen . Ich behaupte nicht, überhaupt ein Experte zu sein. Wenn also jemand eine bessere Möglichkeit hat, einen Teil der Terminologie zu formulieren, fühlen Sie sich frei.

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

Karte

Wenn Sie mit der MapDatenstruktur nicht vertraut sind, lesen Sie bitte die Java Map-Referenz . Kurz gesagt, eine Karte ähnelt einem Wörterbuch oder einem Hash.

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

Bitte zögern Sie nicht, Fragen zu diesem Beitrag zu kommentieren, oder wenn ich etwas nicht klargestellt habe oder wenn ich etwas nicht berührt habe, über das Sie immer noch verwirrt sind ... usw., was auch immer in Ihrem Kopf auftaucht.

(Ich werde abnehmen, wenn Justin Grammens nicht zustimmt. Aber wenn nicht, dann danke Justin, dass er cool ist.)

Aktualisieren

Ich habe gerade einen Kommentar zur Verwendung des Codes erhalten und festgestellt, dass beim Rückgabetyp ein Fehler aufgetreten ist. Die Methodensignatur wurde so festgelegt, dass eine Zeichenfolge zurückgegeben wird. In diesem Fall wurde jedoch nichts zurückgegeben. Ich habe die Signatur in HttpResponse geändert und verweise auf diesen Link unter Abrufen des Antworttextes von HttpResponse. Die Pfadvariable ist die URL. Ich habe sie aktualisiert, um einen Fehler im Code zu beheben.

Terrance
quelle
Danke @Terrance. In einer anderen Klasse erstellt er eine Karte mit verschiedenen Schlüsseln und Werten, die später in JSONObjects umgewandelt werden. Ich habe versucht, etwas Ähnliches zu implementieren, aber ich habe auch keine Erfahrung mit Karten. Ich werde den Code für das, was ich versucht habe, zu meinem ursprünglichen Beitrag hinzufügen. Ihre Erklärungen für das, was seitdem vor sich ging, wurden gemacht, und ich konnte es erfolgreich zum Laufen bringen, indem ich JSONObjects mit fest codierten Namen und Werten erstellte. Vielen Dank!
Woot, ich bin froh, dass ich helfen konnte.
Terrance
Justin sagt, er stimmt zu. Er sollte jetzt genug Repräsentanten haben, um selbst einen Kommentar zu hinterlassen.
Abizern
Ich möchte diesen Code verwenden. Wie gehe ich vor? Bitte geben Sie an, was die Pfadvariable ist und was zurückgegeben werden muss, damit ich auf meinem Java-Ende die Daten abrufen kann.
Prateek
3
Es gibt keinen Grund für getJsonObjectFromMap(): JSONObject hat einen Konstruktor, der Folgendes benötigt Map: developer.android.com/reference/org/json/…
pr1001
41

Hier ist eine alternative Lösung zur Antwort von @ Terrance. Sie können die Konvertierung einfach auslagern. Die Gson-Bibliothek leistet hervorragende Arbeit bei der Konvertierung verschiedener Datenstrukturen in JSON und umgekehrt.

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

Ähnliches kann mit Jackson anstelle von Gson geschehen. Ich empfehle auch einen Blick auf Retrofit, das einen Großteil dieses Boilerplate-Codes für Sie verbirgt. Für erfahrene Entwickler empfehle ich, RxAndroid auszuprobieren .

JJD
quelle
Meine App sendet Daten über die HttpPut-Methode. Wenn der Server eine Anfrage erhält, antwortet er als JSON-Daten. Ich weiß nicht, wie ich Daten von json bekomme. Erzähl es mir bitte. CODE .
Kongkea
@kongkea Bitte werfen Sie einen Blick in die GSON-Bibliothek . Es ist in der Lage, die JSON-Datei in Java-Objekte zu analysieren.
JJD
@JJD Bisher schlagen Sie vor, Daten an den Remote-Server zu senden, und dies ist eine nette Erklärung. Sie möchten jedoch wissen, wie das JSON-Objekt mithilfe des HTTP-Protokolls analysiert wird. Können Sie Ihre Antwort auch mit JSON-Analyse ausarbeiten? Es wird für alle, die neu in diesem Bereich sind, sehr hilfreich sein.
AndroidDev
@AndroidDev Bitte öffnen Sie eine neue Frage, da es sich bei dieser Frage um das Senden von Daten vom Client an den Server handelt. Fühlen Sie sich frei, hier einen Link zu hinterlassen.
JJD
@ JJD Sie rufen abstrakte Methode execute()und es ist natürlich fehlgeschlagen
Konstantin Konopko
33

Ich empfehle stattdessen, dies zu HttpURLConnectionverwenden HttpGet. Wie HttpGetbereits in Android API Level 22 veraltet.

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

Zu viel Code für diese Aufgabe. Überprüfen Sie diese Bibliothek. Https://github.com/kodart/Httpzoid Is verwendet GSON intern und bietet eine API, die mit Objekten funktioniert. Alle JSON-Details sind ausgeblendet.

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
quelle
tolle Lösung, leider fehlt diesem Plugin Gradle-Unterstützung: /
Electronix384128
3

Es gibt verschiedene Möglichkeiten, eine HHTP-Verbindung herzustellen und Daten von einem RESTFULL-Webdienst abzurufen. Der neueste ist GSON. Bevor Sie jedoch mit GSON fortfahren, müssen Sie eine Vorstellung von der traditionellsten Methode zum Erstellen eines HTTP-Clients und zur Datenkommunikation mit einem Remote-Server haben. Ich habe beide Methoden zum Senden von POST & GET-Anforderungen über HTTPClient erwähnt.

/**
 * 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
quelle