Volley JsonObjectRequest Запит на публікацію не працює


78

Я використовую android Volley для надсилання запиту. Тому я використовую цей код. Я не розумію одного. Я перевіряю на своєму сервері, що параметри завжди нульові. Я вважаю, що getParams () не працює. Що мені робити для вирішення цього питання.

 RequestQueue queue = MyVolley.getRequestQueue();
        JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,SPHERE_URL,null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        System.out.println(response);
                        hideProgressDialog();
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                      hideProgressDialog();
                    }
                }) {
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("id","1");
                params.put("name", "myname");
                return params;
            };
        };
        queue.add(jsObjRequest);

5
Thx для вашого запитання. У мене також виникли проблеми з JsonObjectRequest. Отже, я просто використовую звичайний StringRequest, тоді він спрацював. Здається, залповий баг. Чи можу я знати, як ви це вирішили?
Thein

Так, звісно. Ви повинні створити свій CustomJsonObjectRequest як тут stackoverflow.com/questions/19837820 / ...
PMB

Дякую за питання! У мене теж таке ж питання ..
Бала Вішну

1
тому що 3-й параметр вашого конструктора є нульовим.
njzk2

@ njzk2: Я думаю, що pmb намагається надіслати запит POST із зашифрованими url-параметрами, а не тіло JSON, для чого призначений третій аргумент. Відповідь LOG_TAG видається найбільш вдалою: користувацький клас, який приймає параметри і все ще дозволяє відповідь JSON.
дванадцять17,

Відповіді:


134

спробуйте скористатися цим допоміжним класом

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

В операції / фрагменті використовуйте це

RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
CustomRequest jsObjRequest = new CustomRequest(Method.POST, url, params, this.createRequestSuccessListener(), this.createRequestErrorListener());

requestQueue.add(jsObjRequest);

1
Thx це працює! Чому перевизначення getParams () у JsonObjectRequest не працює? Це помилка волейболу?
Thein

1
це не помилка, getParams () не викликається, оскільки JsonObjectRequest розширив JsonRequest, який викликає getBody () безпосередньо для кодування другого параметра конструктора (виклик requestBody) як contentType, тому він ігнорує ваш метод getParam ().
VinceStyling

1
@LOG_TAG що таке this.createRequestSuccessListener (), this.createRequestErrorListener ()); Я не розумію цього, будь ласка, поясніть.
ik024

2
@Droider Це методи, які створюють належні об'єкти обробки відповідей. Швидше за все, вони зроблені як індивідуальні методи з метою читабельності. Ви можете точно так само створити об’єкти на місці за допомогою newключового слова, але залежно від розміру коду для цих об’єктів може бути важко прочитати з одного погляду.
jnfjnjtj

2
у мене було багато питань, і це працює приємно: D дякую
Хав'єр

30

Ви можете створити власний JSONObjectReuqestі перевизначити getParamsметод, або ви можете надати їх у конструкторі як JSONObjectдля розміщення в тілі запиту.

Ось так (я відредагував ваш код):

JSONObject obj = new JSONObject();
obj.put("id", "1");
obj.put("name", "myname");

RequestQueue queue = MyVolley.getRequestQueue();
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,SPHERE_URL,obj,
    new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
             System.out.println(response);
             hideProgressDialog();
        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
             hideProgressDialog();
        }
    });
queue.add(jsObjRequest);

приємно і швидко! але якщо вам потрібен x-www-urlencoded, це робиться залпом?
Путратор

Я не впевнений, але ви можете легко його перевірити.
Itai Hanski

Ви впевнені, що getParams не викликається? На противагу цьому код показує його називають getBody () і getPostParams () , і ви говорите собі суперечить тут: stackoverflow.com/questions/18484647 / ...
Poutrathor

Ви маєте рацію, я переплутався між методами (недостатньо сну). Я відредагував свою відповідь.
Itai Hanski

спробували за допомогою методів POST та GET. обидва не працюють. Я без ідеї.
Амір Фазван

5

Легкий для мене! Я отримав це кілька тижнів тому:

Це стосується getBody()методу, а не методуgetParams() для запиту на публікацію.

Ось мій:

    @Override
/**
 * Returns the raw POST or PUT body to be sent.
 *
 * @throws AuthFailureError in the event of auth failure
 */
public byte[] getBody() throws AuthFailureError {
    //        Map<String, String> params = getParams();
    Map<String, String> params = new HashMap<String, String>();
    params.put("id","1");
    params.put("name", "myname");
    if (params != null && params.size() > 0) {
        return encodeParameters(params, getParamsEncoding());
    }
    return null;

}

(Я припускав, що ви хочете розмістити параметри, які ви написали у своєму getParams)

Я дав параметри запиту всередині конструктора, але оскільки ви створюєте запит на льоту, ви можете жорстко їх закодувати всередині вашого перевизначення методу getBody ().

Ось так виглядає мій код:

    Bundle param = new Bundle();
    param.putString(HttpUtils.HTTP_CALL_TAG_KEY, tag);
    param.putString(HttpUtils.HTTP_CALL_PATH_KEY, url);
    param.putString(HttpUtils.HTTP_CALL_PARAM_KEY, params);

    switch (type) {
    case RequestType.POST:
        param.putInt(HttpUtils.HTTP_CALL_TYPE_KEY, RequestType.POST);
        SCMainActivity.mRequestQueue.add(new SCRequestPOST(Method.POST, url, this, tag, receiver, params));

і якщо ви хочете ще більше, останні параметри рядка походять з:

param = JsonUtils.XWWWUrlEncoder.encode(new JSONObject(paramasJObj)).toString();

а paramasJObj приблизно такий: {"id"="1","name"="myname"}звичайний рядок JSON.


Я не розумію, як передавати параметри тут. Рядок s = новий рядок (параметр). Що це?
pmb

це просто рядок з моїми параметрами там. Я відправляю це в конструктор. Я покажу вам ще трохи.
Путратор

Дякую @poutrathor, якщо ви можете сказати мені, як надіслати ті параметри, що в методі getParams ().
pmb

ах Отже, ви хочете використовувати їх як параметри. Що ви публікуєте на своєму сервері з цікавістю?
Путратор

Моя мета полягає в тому, що я повинен відправляти параметри, як написано в getParams, я не можу відправити туди jsonObject.
pmb

3

Коли ви працюєте з запитом JsonObject, вам потрібно передати параметри відразу після того, як ви переходите за посиланням в ініціалізації, подивіться на цей код:

        HashMap<String, String> params = new HashMap<>();
        params.put("user", "something" );
        params.put("some_params", "something" );

    JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, "request_URL", new JSONObject(params), new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {

           // Some code 

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


}

1

Все, що вам потрібно зробити, це перевизначити метод getParams у класі Request. У мене була та сама проблема, і я шукав відповіді, але не міг знайти правильної. Проблема на відміну від запиту на отримання, параметри повідомлення, які перенаправляються серверами, можуть бути скинуті. Наприклад, прочитайте це . Тож, не ризикуйте, щоб ваші запити були перенаправлені веб-сервером. Якщо ви націлюєтесь на http: // example / myapp , тоді вкажіть точну адресу вашої служби, тобто http://example.com/myapp/index.php .
З волейлером все в порядку і працює чудово, проблема походить десь в іншому місці.


1

Функція заміни getParams відмінно працює. Ви використовуєте метод POST і встановили значення jBody як нульове. Тому це не працює. Ви можете використовувати метод GET, якщо хочете надіслати нульовий jBody. Я перевизначив метод getParams, і він працює або з методом GET (і null jBody), або з методом POST (і jBody! = Null)

Також є всі приклади тут


1

У мене була одна і та ж проблема одного разу, порожній масив POST спричинений перенаправленням запиту (на стороні вашого сервера), виправте URL-адресу, щоб її не потрібно було перенаправляти, коли вона потрапляє на сервер. Наприклад, якщо https примусово використовується файл .htaccess у вашому додатку на стороні сервера, переконайтеся, що ваш запит клієнта має префікс "https: //". Зазвичай, коли відбувається переспрямування, масив POST втрачається. Сподіваюся, це допоможе!


0

Це спрацювало, можна спробувати це для виклику за допомогою Volley Json Request and Response ith Java Code.

public void callLogin(String sMethodToCall, String sUserId, String sPass) {
        RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());

        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
                Request.Method.POST, ConstantValues.ROOT_URL_LOCAL + sMethodToCall.toString().trim(), addJsonParams(sUserId, sPass),
//                JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, object,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d("onResponse", response.toString());
                        Toast.makeText(VolleyMethods.this, response.toString(), Toast.LENGTH_LONG).show(); // Test

                        parseResponse(response);
//                        msgResponse.setText(response.toString());
//                        hideProgressDialog();
                    }
                },
                new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.d("onErrorResponse", "Error: " + error.getMessage());
                        Toast.makeText(VolleyMethods.this, error.toString(), Toast.LENGTH_LONG).show();
//                hideProgressDialog();
                    }
                }) {

            /**
             * Passing some request headers
             */
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Content-Type", "application/json; charset=utf-8");
                return headers;
            }


        };

        requestQueue.add(jsonObjectRequest);
    }

    public JSONObject addJsonParams(String sUserId, String sPass) {
        JSONObject jsonobject = new JSONObject();
        try {
//            {"id":,"login":"secretary","password":"password"}

            ///***//
            Log.d("addJsonParams", "addJsonParams");

//            JSONObject jsonobject = new JSONObject();

//            JSONObject jsonobject_one = new JSONObject();
//
//            jsonobject_one.put("type", "event_and_offer");
//            jsonobject_one.put("devicetype", "I");
//
//            JSONObject jsonobject_TWO = new JSONObject();
//            jsonobject_TWO.put("value", "event");
//            JSONObject jsonobject = new JSONObject();
//
//            jsonobject.put("requestinfo", jsonobject_TWO);
//            jsonobject.put("request", jsonobject_one);

            jsonobject.put("id", "");
            jsonobject.put("login", sUserId); // sUserId
            jsonobject.put("password", sPass); // sPass


//            js.put("data", jsonobject.toString());

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

        return jsonobject;
    }

    public void parseResponse(JSONObject response) {

        Boolean bIsSuccess = false; // Write according to your logic this is demo.
        try {
            JSONObject jObject = new JSONObject(String.valueOf(response));
            bIsSuccess = jObject.getBoolean("success");


        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(VolleyMethods.this, "" + e.toString(), Toast.LENGTH_LONG).show(); // Test
        }

    }

0



побудувати gradle (додаток)

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.1.0'
    implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation 'com.android.volley:volley:1.1.1'
}

android-маніфест
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

MainActivity
Коли ви використовуєте JsonObjectRequest, обов'язково надсилайте jsonobject і отримуйте jsonobject, інакше ви отримаєте помилку, оскільки він приймає лише jsonobject.
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley

fun peticion(){
    val jsonObject = JSONObject()
    jsonObject.put("user", "jairo")
    jsonObject.put("password", "1234")
    val queue = Volley.newRequestQueue(this)
    val url = "http://192.168.0.3/get_user.php"
    // GET: JsonObjectRequest( url, null,
    // POST: JsonObjectRequest( url, jsonObject,
    val jsonObjectRequest = JsonObjectRequest( url, jsonObject,
        Response.Listener { response ->
            // Check if the object 'msm' does not exist
            if(response.isNull("msm")){
                println("Name: "+response.getString("nombre1"))
            }
            else{
                // If the object 'msm' exists we print it
                println("msm: "+response.getString("msm"))
            }
        },
        Response.ErrorListener { error ->
            error.printStackTrace()
            println(error.toString())
        }
    )
    queue.add(jsonObjectRequest)
}

файл php get_user.php
<?php
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Headers: *");
    // we receive the parameters
    $json = file_get_contents('php://input');
    $params = json_decode($json);
    error_reporting(0);
    require_once 'conexion.php';

    $mysqli=getConex();
    $user=$params->user;
    $password=$params->password;
    $res=array();
    $verifica_usuario=mysqli_query($mysqli,"SELECT * FROM usuarios WHERE usuario='$user' and clave='$password'");
    if(mysqli_num_rows($verifica_usuario)>0){
        $query="SELECT * FROM usuarios WHERE usuario='$user'";
        $result=$mysqli->query($query);
        while($row = $result->fetch_array(MYSQLI_ASSOC)){
            $res=$row;
        }
    }
    else{
        $res=array('msm'=>"Incorrect user or password");
    }
    $jsonstring = json_encode($res);
    header('Content-Type: application/json');
    echo $jsonstring;
?>

файл php conexion - -
<?php
    function getConex(){
        $servidor="localhost";
        $usuario="root";
        $pass="";  
        $base="db";
        
        $mysqli = mysqli_connect($servidor,$usuario,$pass,$base);
        if (mysqli_connect_errno($mysqli)){
            echo "Fallo al conectar a MySQL: " . mysqli_connect_error();
        }
        $mysqli->set_charset('utf8');
        return $mysqli;
    }
?>

Не могли б ви пояснити цей код? Зараз трохи незрозуміло, як це вирішує проблему.
Райан М
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.