Volley - параметри POST / GET


81

Я бачив сесію Google IO 2013 про волейбол, і я розглядаю можливість переходу на залп. Чи підтримує Volley додавання параметрів POST / GET на запит? Якщо так, як я можу це зробити?


2
Я не бачив цілого виступу, але я впевнений, що GET має бути здійсненним, просто додавши параметри до URL-адреси (наприклад, http://example.com?param1=val1&param2=val2)
JJJollyjim

Здається, документації поки що немає, але ви можете перевірити джерело тут android.googlesource.com/platform/frameworks/volley/+/master
MM.

@ JJ56 - Так, але як щодо параметрів POST? Я побачив вихідний код, але не знайшов нічого, що стосується параметрів POST.
Ziem

1
Мені соромно це говорити. Але, якщо ви потрапили сюди і запитали, чому у вашому запиті немає тіла на вашому сервері, переконайтеся, що ви використовуєте метод POST / PUT. Думаю, я просто втомився. Сподіваюся, цей коментар комусь допоможе або допоможе мені почуватись краще
Елвін Кеслер,

Відповіді:


64

У класі Request (що розширює Request) перевизначте метод getParams (). Ви зробили б те саме для заголовків, просто перевизначивши getHeaders ().

Якщо ви подивитесь на клас PostWithBody у TestRequest.java в тестах Volley, ви знайдете приклад. Це приблизно так

public class LoginRequest extends Request<String> {

    // ... other methods go here

    private Map<String, String> mParams;

    public LoginRequest(String param1, String param2, Listener<String> listener, ErrorListener errorListener) {
        super(Method.POST, "http://test.url", errorListener);
        mListener = listener;
        mParams = new HashMap<String, String>();
        mParams.put("paramOne", param1);
        mParams.put("paramTwo", param2);

    }

    @Override
    public Map<String, String> getParams() {
        return mParams;
    }
}

Еван Чарлтон був люб’язним, щоб швидко зробити приклад проекту, який показав нам, як користуватися залпом. https://github.com/evancharlton/folly/


71
Зверніть увагу, що getParamsвикликається лише (за замовчуванням) у запиті POST або PUT, але не в запиті GET. Дивіться відповідь Ogre_BGR
Itai Hanski

2
Не можу повірити, що ніколи цього не помічав
Афзал Н

@AfzalivE, будь-яка ідея про те, як підписати запит API за допомогою OAuth при використанні наведеного вище коду?
Біпін Ваялу

2
@BipinVayalu Якщо ви підключаєтесь до Google API, ви повинні мати можливість використовувати com.android.volley.AndroidAuthenticator
Pierre-Antoine

Ви забули створити екземпляр mParams.
Моріц

86

Для параметрів GET існує дві альтернативи:

По-перше : Як пропонується у коментарі під запитанням, ви можете просто використовувати String і замінити заповнювачі параметрів їх значеннями, такими як:

String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s&param2=%2$s",
                           num1,
                           num2);

StringRequest myReq = new StringRequest(Method.GET,
                                        uri,
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener());
queue.add(myReq);

де num1 та num2 - це рядкові змінні, що містять ваші значення.

По-друге : Якщо ви використовуєте новіший зовнішній HttpClient (наприклад, 4.2.x), ви можете використовувати URIBuilder для створення вашого Uri. Перевага полягає в тому, що якщо у вашому рядку uri вже є параметри, буде простіше передати його в, URIBuilderа потім використовувати ub.setQuery(URLEncodedUtils.format(getGetParams(), "UTF-8"));для додавання додаткових параметрів. Таким чином ви не потурбуєтесь перевірити, чи "?" вже додано до uri або пропустити деякі і таким чином усунувши джерело потенційних помилок.

Для параметрів POST, можливо, іноді буде простіше, ніж прийнята відповідь, зробити це так:

StringRequest myReq = new StringRequest(Method.POST,
                                        "http://somesite.com/some_endpoint.php",
                                        createMyReqSuccessListener(),
                                        createMyReqErrorListener()) {

    protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
        Map<String, String> params = new HashMap<String, String>();
        params.put("param1", num1);
        params.put("param2", num2);
        return params;
    };
};
queue.add(myReq);

наприклад, просто замінити getParams()метод.

Ви можете знайти робочий приклад (поряд з багатьма іншими основними прикладами волейболу) у проекті Andorid Volley Examples .


Я наслідував ваші приклади Волей. Наразі це найкорисніший код Volly, але у мене є проблеми з JsonObjectRequest. Я отримав стару відповідь у createMyReqSuccessListener, доки її не встановив знову. Чи зберігаються дані волейболу в кеші? Будь ласка, підкажіть спосіб зробити це.
SkyWalker

2
Кэшируются лише зображення. Будь ласка, перевірте, чи є якийсь проксі, що перехоплює ваші запити. Якщо в запитах є однаково однакова URL-адреса, і можливо, проксі просто повертає перший результат.
Огнян

2
Існує плагін для Firefox під назвою "Тест ресурсів HTTP", який дозволяє надсилати запити через веб-сервер. Це дуже корисно для тестування таких випадків. Просто введіть свою URL-адресу (і параметри POST, якщо такі є) і подивіться, якою є відповідь сервера на кілька послідовних запитів. Якщо знову ви отримаєте той самий результат відповіді, швидше за все, кешований. У цьому випадку ви можете перевірити повернені заголовки, щоб перевірити, чи є заголовки проксі. Про "no-cache" - так, це повинно спрацювати.
Огнян

2
Я пропоную вам відкрити окреме запитання, щоб інші могли приєднатися та допомогти. Будь ласка, надайте інформацію, для якого стеку ви використовуєте HURL або HttpClient, а також версію для Android, проти якої ви тестуєте. Будь ласка, розмістіть тут посилання на нове питання, щоб люди могли стежити за обговоренням.
Огнян

3
@Yousif Можливо, ви отримаєте набагато кращі відповіді, якщо задасте це як нове запитання, але коротше: запит POST дозволяє надсилати файли та інші великі дані, які не вміщуються в запиті GET. Крім того, існує ризик безпеки при використанні запиту GET, оскільки URL-адреса може реєструватися на сервері, таким чином викриваючи конфіденційні дані.
Огнян

23

CustomRequest - це спосіб вирішити JSONObjectRequest Volley не може публікувати такі параметри, як StringRequest

ось допоміжний клас, який дозволяє додавати параметри:

    import java.io.UnsupportedEncodingException;
    import java.util.Map;    
    import org.json.JSONException;
    import org.json.JSONObject;    
    import com.android.volley.NetworkResponse;
    import com.android.volley.ParseError;
    import com.android.volley.Request;
    import com.android.volley.Response;
    import com.android.volley.Response.ErrorListener;
    import com.android.volley.Response.Listener;
    import com.android.volley.toolbox.HttpHeaderParser;

    public class CustomRequest extends Request<JSONObject> {

    private Listener<JSONObject> listener;
    private Map<String, String> params;

    public CustomRequest(String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return params;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        listener.onResponse(response);
    }

}

завдяки Грінчіу


@WarrenFaith Дякую за вказівку, я оновив відповідь!
LOG_TAG

3
Велике спасибі, я шукав години, перш ніж отримати це рішення. Це настільки дивно, що перевизначення getParams()функції JSONObjectReuqest не працює.
Валід Аммар

@MohammadWalid FYI читати цю stackoverflow.com/questions/16902716 / ... і спробувати використовувати дооснащення! як залп, так і модернізацію можна використовувати з okhttp!
LOG_TAG

Я спробував це рішення, але мені не вдалося. getParams () не викликається.
Махді,

10

Цей допоміжний клас управляє параметрами для запитів GET та POST :

import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;    

import org.json.JSONException;
import org.json.JSONObject;

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;

public class CustomRequest extends Request<JSONObject> {
    private int mMethod;
    private String mUrl;
    private Map<String, String> mParams;
    private Listener<JSONObject> mListener;

    public CustomRequest(int method, String url, Map<String, String> params,
            Listener<JSONObject> reponseListener, ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mMethod = method;
        this.mUrl = url;
        this.mParams = params;
        this.mListener = reponseListener;
    }

@Override
public String getUrl() {
    if(mMethod == Request.Method.GET) {
        if(mParams != null) {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            Iterator<Map.Entry<String, String>> iterator = mParams.entrySet().iterator();
            int i = 1;
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                if (i == 1) {
                    stringBuilder.append("?" + entry.getKey() + "=" + entry.getValue());
                } else {
                    stringBuilder.append("&" + entry.getKey() + "=" + entry.getValue());
                }
                iterator.remove(); // avoids a ConcurrentModificationException
                i++;
            }
            mUrl = stringBuilder.toString();
        }
    }
    return mUrl;
}

    @Override
    protected Map<String, String> getParams()
            throws com.android.volley.AuthFailureError {
        return mParams;
    };

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        // TODO Auto-generated method stub
        mListener.onResponse(response);
    }
}

Це вирішує додавання параметрів до методу GET, дякую!
pkarc

2
У нашому випадку підхід ітератора знищив оригінальний об'єкт Map params, який ми передали функції. Здається, Воллі GetUrlкілька разів телефонує внутрішньо . Ми закінчили з класичним підходом foreach, як викладено в окремій відповіді. Сподіваюся, це допоможе тому, хто тут приземлиться. :)
Паоло Касчієлло,

Як викликати цей допоміжний клас для отримання запиту з 3 параметрами
kgandroid

@kgandroid, створіть Map <String, String> зі своїми ключами та значеннями. Приклад: Map <String, String> params = new HashMap <String, String> (); params.put ("param1", "value1"); params.put ("param2", "value2"); params.put ("param3", "value3");
Андреа Мотто,

6

Працюючи з параметрами GET, я повторював рішення Андреа Мотто. Проблема полягала в тому, що зателефонував ВолліGetUrl кілька разів, і його рішення, використовуючи Ітератор, знищило оригінальний об'єкт Карти. Подальші внутрішні виклики Volley мали порожній об'єкт params.

Я також додав кодування параметрів.

Це вбудоване використання (без підкласу).

public void GET(String url, Map<String, String> params, Response.Listener<String> response_listener, Response.ErrorListener error_listener, String API_KEY, String stringRequestTag) {
    final Map<String, String> mParams = params;
    final String mAPI_KEY = API_KEY;
    final String mUrl = url;

    StringRequest stringRequest = new StringRequest(
            Request.Method.GET,
            mUrl,
            response_listener,
            error_listener
    ) {
        @Override
        protected Map<String, String> getParams() {
            return mParams;
        }

        @Override
        public String getUrl() {
            StringBuilder stringBuilder = new StringBuilder(mUrl);
            int i = 1;
            for (Map.Entry<String,String> entry: mParams.entrySet()) {
                String key;
                String value;
                try {
                    key = URLEncoder.encode(entry.getKey(), "UTF-8");
                    value = URLEncoder.encode(entry.getValue(), "UTF-8");
                    if(i == 1) {
                        stringBuilder.append("?" + key + "=" + value);
                    } else {
                        stringBuilder.append("&" + key + "=" + value);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                i++;

            }
            String url = stringBuilder.toString();

            return url;
        }

        @Override
        public Map<String, String> getHeaders() {
            Map<String, String> headers = new HashMap<>();
            if (!(mAPI_KEY.equals(""))) {
                headers.put("X-API-KEY", mAPI_KEY);
            }
            return headers;
        }
    };

    if (stringRequestTag != null) {
        stringRequest.setTag(stringRequestTag);
    }

    mRequestQueue.add(stringRequest);
}

Ця функція використовує заголовки для передачі файлу APIKEY і встановлює TAG для запиту, корисного для його скасування до його завершення.

Сподіваюся, це допомагає.


3

Це може вам допомогти ...

private void loggedInToMainPage(final String emailName, final String passwordName) {

    String tag_string_req = "req_login";
    StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://localhost/index", new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.d(TAG, "Login Response: " + response.toString());
            try {
                JSONObject jsonObject = new JSONObject(response);
                Boolean error = jsonObject.getBoolean("error");
                if (!error) {

                    String uid = jsonObject.getString("uid");
                    JSONObject user = jsonObject.getJSONObject("user");
                    String email = user.getString("email");
                    String password = user.getString("password");


                    session.setLogin(true);
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                    finish();
                    Toast.makeText(getApplicationContext(), "its ok", Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            System.out.println("volley Error .................");
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<String, String>();
            params.put("tag", "login");
            params.put("email", emailName);
            params.put("password", passwordName);
            return params;
        }
    };


    MyApplication.getInstance().addToRequestQueue(stringRequest,tag_string_req);
}

3

Для майбутніх читачів

Я люблю працювати з Волей . Щоб заощадити час на розробку, я спробував написати невелику зручну бібліотеку Gloxey Netwok Manager для налаштування Volley зі своїм проектом. Він включає парсер JSON та різні інші методи, які допомагають перевірити доступність мережі.

Використання, ConnectionManager.classпри якому доступні різні методи для запиту Volley String та Volley JSON . Ви можете робити запити на GET, PUT, POST, DELETE із заголовком або без нього. Ви можете прочитати повну документацію тут .

Просто помістіть цей рядок у файл gradle.

  dependencies { 

       compile 'io.gloxey.gnm:network-manager:1.0.1'
   }

Запит на волейбол

Метод GET (без заголовка)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, volleyResponseInterface);

Як користуватись?

     Configuration                Description

     Context                      Context 
     isDialog                     If true dialog will appear, otherwise not.
     progressView                 For custom progress view supply your progress view id and make isDialog true. otherwise pass null. 
     requestURL                   Pass your API URL.  
     volleyResponseInterface      Callback for response.  

Приклад

    ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

Запит на волейбол

Метод POST / PUT / DELETE (без заголовка)

    ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, requestMethod, params, volleyResponseInterface);

Приклад

Use Method : Request.Method.POST
             Request.Method.PUT
             Request.Method.DELETE

Your params : 

HashMap<String, String> params = new HashMap<>();
params.put("param 1", "value");
params.put("param 2", "value");

ConnectionManager.volleyStringRequest(this, true, null, "url", Request.Method.POST, params, new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */
    }

    @Override
    public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
    }
});

Бонус

Gloxey JSON Парсер

Не соромтеся використовувати синтаксичний аналізатор gloxey json для синтаксичного аналізу вашої відповіді API.

  YourModel yourModel = GloxeyJsonParser.getInstance().parse(stringResponse, YourModel.class);

Приклад

ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
    @Override
    public void onResponse(String _response) {

        /**
         * Handle Response
         */

         try {

          YourModel yourModel = GloxeyJsonParser.getInstance().parse(_response, YourModel.class);

            } catch (Exception e) {
                e.printStackTrace();
            }

    }

    @Override
     public void onErrorResponse(VolleyError error) {

        /**
         * handle Volley Error
         */
         if (error instanceof TimeoutError || error instanceof NoConnectionError) {

                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                     //handle retry button

                    }
                });

            } else if (error instanceof AuthFailureError) {
            } else if (error instanceof ServerError) {
            } else if (error instanceof NetworkError) {
            } else if (error instanceof ParseError) {
            }

    }

    @Override
    public void isNetwork(boolean connected) {

        /**
         * True if internet is connected otherwise false
         */
          if (!connected) {
                showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //Handle retry button
                    }
                });
    }
});


     public void showSnackBar(View view, String message) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
     }

     public void showSnackBar(View view, String message, String actionText, View.OnClickListener onClickListener) {
            Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction(actionText, onClickListener).show();
     }

Але чи підтримує це метод. Отримати
Девід

Так, це, будь ласка, подивіться деталі. github.com/adnanbinmustafa/Gloxey-Network-Manager
Аднан Бін Мустафа

0

Щоб надати POSTпараметр, надішліть свій параметр як JSONObject у JsonObjectRequestконструкторі. Третій параметр приймає значення, JSONObjectяке використовується в тілі запиту.

JSONObject paramJson = new JSONObject();

paramJson.put("key1", "value1");
paramJson.put("key2", "value2");


JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,url,paramJson,
    new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {

        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });
requestQueue.add(jsonObjectRequest);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.