Як відправити POST-запит у JSON за допомогою HTTPClient в Android?


111

Я намагаюся розібратися, як POST JSON з Android за допомогою HTTPClient. Я деякий час намагався розібратися в цьому, я знайшов в Інтернеті безліч прикладів, але жодного з них я не можу працювати. Я вважаю, це через відсутність моїх знань JSON / мереж взагалі. Я знаю, що є багато прикладів, але хтось міг би вказати мені на фактичний підручник? Я шукаю покроковий процес із кодом та поясненням того, чому ви робите кожен крок, або того, що цей крок робить. Це не повинно бути складним, достатньо простого.

Знову ж таки, я знаю, що є багато прикладів, я просто дійсно шукаю приклад з поясненням того, що саме відбувається і чому це робиться саме так.

Якщо хтось знає про хорошу книгу Android про це, то, будь ласка, дайте мені знати.

Ще раз дякую за допомогу @terrance, ось код, який я описав нижче

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

Можливо, ви можете опублікувати один із прикладів, на який ви не можете працювати? Отримавши щось робоче, ви дізнаєтесь, як шматки складаються між собою.
fredw

Відповіді:


157

У цій відповіді я використовую приклад, опублікований Джастіном Грамменсом .

Про JSON

JSON розшифровується як JavaScript Object Notation. У властивостях JavaScript можна посилатися як на це, так object1.nameі на це object['name'];. У прикладі зі статті використовується цей біт JSON.

Частини
Вентилятор-об'єкт із електронною поштою як ключовим і foo@bar.com як значення

{
  fan:
    {
      email : 'foo@bar.com'
    }
}

Так еквівалент об'єкта був би fan.email;або fan['email'];. Обидва мають однакове значення 'foo@bar.com'.

Про HttpClient Request

Далі - це те, що наш автор використав для оформлення HttpClient Request . Я взагалі не претендую на те, щоб бути експертом, тому якщо хтось має кращий спосіб висловити частину термінології, почувайтеся вільними.

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

Карта

Якщо ви не знайомі зі Mapструктурою даних, перегляньте посилання на карту Java . Коротше кажучи, карта схожа на словник чи хеш.

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 'foo@bar.com' 
    //{ fan: { email : 'foo@bar.com' } }

    //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 'foo@bar.com'  together in map
        holder.put(key, data);
    }
    return holder;
}

Будь ласка, не соромтесь коментувати будь-які питання, що виникають з приводу цієї публікації, або якщо я не зробив щось зрозуміле, або якщо я не зачіпав те, що ваше все ще плутало ... тощо.

(Я зніму, якщо Джастін Гремменс не схвалює. Але якщо ні, то дякую Джастіну за те, що він про це класно.)

Оновлення

Я просто чекаю отримати коментар про те, як використовувати код і зрозумів, що в типі повернення сталася помилка. Підпис методу було встановлено для повернення рядка, але в цьому випадку він нічого не повертав. Я змінив підпис на HttpResponse і перешлю вас за цим посиланням у розділі Отримання тіла відповіді HttpResponse, змінна шлях є URL-адресою, і я оновив, щоб виправити помилку в коді.


Дякую @Terrance. Отже, в іншому класі він створює карту з різними ключами та значеннями, які згодом перетворяться на JSONObjects. Я спробував реалізувати щось подібне, але у мене також немає досвіду роботи з картами, я додам код для того, що я спробував реалізувати, до своєї початкової публікації. Ваші пояснення того, що відбувалося з тих пір, і мені вдалося змусити його працювати, створивши JSONObjects з жорстко кодованими іменами та значеннями. Дякую!

Вут, рада, що можу допомогти.
Терранс

Джастін каже, що схвалює. Він повинен мати достатньо представника, щоб прийти і залишити коментар сам до цього часу.
Abizern

Я хочу використовувати цей код. Як мені це зробити? Вкажіть, будь ласка, що є змінною шляху та що потрібно повернути, щоб я міг отримати дані на своєму Java-коні.
Prateek

3
Причин для цього немає getJsonObjectFromMap(): JSONObject має конструктор, який приймає Map: developer.android.com/reference/org/json/…
pr1001

41

Ось альтернативне рішення відповіді @ Terrance. Ви можете легко передати конверсію. Бібліотека Gson робить чудову роботу, перетворюючи різні структури даних в JSON і навпаки.

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

Подібне можна зробити, використовуючи Джексона замість Гсона. Я також рекомендую поглянути на Retrofit, який приховує для вас багато цього кодового коду. Для більш досвідчених розробників рекомендую спробувати RxAndroid .


мій додаток надсилає дані через HttpPut method.when сервер отримав запит, він відповідає як дані json. Я не знаю, як отримати дані від json. будь-ласка скажи мені. КОД .
kongkea

@kongkea Загляньте в бібліотеку GSON . Він здатний аналізувати файл JSON на об’єкти Java.
JJD

@JJD Поки що ви пропонуєте це відправити дані на віддалений сервер, і це приємне пояснення, але хочете знати, як розібрати об'єкт JSON за допомогою протоколу HTTP. Чи можете ви також розробити свою відповідь за допомогою JSON розбору. Це буде дуже корисно для всіх, хто є новим у цьому.
AndroidDev

@AndroidDev Будь ласка, відкрийте нове запитання, оскільки це питання стосується надсилання даних від клієнта на сервер. Сміливо можете перейти сюди посилання.
JJD

@JJD ви називаєте абстрактний метод, execute()і це, безумовно, не вдалося
Костянтин Конопко

33

Я рекомендую використовувати це HttpURLConnectionзамість цього HttpGet. Як HttpGetуже застаріло в Android API рівня 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();
} 

5

Занадто багато коду для цього завдання, перевірте цю бібліотеку https://github.com/kodart/Httpzoid Чи використовується GSON внутрішньо та надає API, який працює з об’єктами. Всі деталі JSON приховані.

Http http = HttpFactory.create(context);
http.get("http://example.com/users")
    .handler(new ResponseHandler<User[]>() {
        @Override
        public void success(User[] users, HttpResponse response) {
        }
    }).execute();

чудове рішення, на жаль, цьому плагіну не вистачає підтримки gradle: /
electronix384128

3

Існує кілька способів встановити HHTP-з'єднання та отримати дані з RESTFULL веб-сервісу. Найновіший - GSON. Але перш ніж перейти до GSON, ви повинні мати деяке уявлення про най традиційніший спосіб створення HTTP-клієнта та здійснення передачі даних з віддаленим сервером. Я згадав обидва способи надсилання запитів POST & GET за допомогою 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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.