La solicitud de publicación Volley JsonObjectRequest no funciona

78

Estoy usando Android Volley para hacer una solicitud. Entonces uso este código. No entiendo nada. Verifico en mi servidor que params es siempre nulo. Considero que getParams () no funciona. ¿Qué debo hacer para solucionar este problema?

 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);
pmb
fuente
5
Gracias por tu pregunta. También tuve problemas con JsonObjectRequest. Entonces, solo uso StringRequest normal y luego funcionó. Parece un error de volea. ¿Puedo saber cómo resolvió eso?
Thein
Sí, por supuesto. tienes que crear tu CustomJsonObjectRequest como aquí stackoverflow.com/questions/19837820/…
pmb
¡Gracias por preguntar! Yo también tengo el mismo problema ..
Bala Vishnu
1
porque el tercer parámetro de su constructor es nulo.
njzk2
@ njzk2: Creo que pmb está tratando de enviar una solicitud POST con parámetros codificados en URL, no un cuerpo JSON, que es para lo que sirve el tercer argumento. La respuesta de LOG_TAG parece la más ap: una clase personalizada que acepta parámetros y aún permite una respuesta JSON.
doce 17 de

Respuestas:

134

intenta usar esta clase de ayuda

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

En actividad / fragmento use esto

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

requestQueue.add(jsObjRequest);
LOG_TAG
fuente
1
¡Gracias, funciona! ¿Por qué anular getParams () en JsonObjectRequest no funciona? ¿Es el error de Volley?
Thein
1
esto no es un error, getParams () no se invoca porque JsonObjectRequest extendió JsonRequest que invoca getBody () directamente para codificar el segundo parámetro del constructor (llamada requestBody) como contentType, por eso ignora su método getParam ().
VinceStyling
1
@LOG_TAG qué es this.createRequestSuccessListener (), this.createRequestErrorListener ()); No lo entiendo por favor explique.
ik024
2
@Droider Esos son métodos que crean los objetos de manejo de respuesta adecuados. Lo más probable es que estén hechos para ser métodos individuales con fines de legibilidad. También puede crear los objetos en su lugar con la newpalabra clave, pero dependiendo del tamaño del código para esos objetos, puede ser difícil de leer de un vistazo.
jnfjnjtj
2
Yo estaba teniendo un montón de problemas, y este bonito trabajo: D gracias
Javier
30

Puede crear un método personalizado JSONObjectReuqesty anular el getParamsmétodo, o puede proporcionarlos en el constructor JSONObjectpara que se coloquen en el cuerpo de la solicitud.

Así (edité tu código):

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);
Itai Hanski
fuente
agradable y rapido! pero si necesita x-www-urlencoded, ¿se hace por volea?
Poutrathor
No estoy seguro, pero puedes probarlo fácilmente.
Itai Hanski
¿Estás seguro de que no se llama a getParams? Por el contrario, el código muestra que es llamado por getBody () y getPostParams () y usted dice lo contrario aquí: stackoverflow.com/questions/18484647/…
Poutrathor
Tienes razón, me confundí entre los métodos (no dormir lo suficiente). Edité mi respuesta.
Itai Hanski
probado con el método POST y GET. ambos no funcionan. No tengo idea.
Amir Fazwan
5

¡Fácil para mí! Lo conseguí hace unas semanas:

Esto entra en el getBody()método, no en getParams()una solicitud de publicación.

Aquí esta el mio :

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

}

(Supuse que quieres PUBLICAR los parámetros que escribiste en tu getParams)

Le di los parámetros a la solicitud dentro del constructor, pero como está creando la solicitud sobre la marcha, puede codificarlos dentro de su anulación del método getBody ().

Así es como se ve mi código:

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

y si quieres aún más, este último parámetro de cadena proviene de:

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

y paramasJObj es algo como esto: {"id"="1","name"="myname"}la cadena JSON habitual.

Poutrathor
fuente
No entiendo cómo pasar parámetros aquí. Cadena s = nueva Cadena (param). ¿Qué es?
pmb
es solo una cadena con mis parámetros allí. Lo envío en el constructor. Te mostraré algunos más.
Poutrathor
Gracias @poutrathor si me puedes decir cómo enviar esos parámetros en el método getParams ().
pmb
ah. Entonces quieres usarlos como params. ¿Qué publicas en tu servidor por curiosidad?
Poutrathor
Mi objetivo es que tengo que enviar parámetros como se escribió en getParams, no puedo enviar jsonObject allí.
pmb
3

Cuando trabaja con la solicitud de JsonObject, debe pasar los parámetros justo después de pasar el enlace en la inicialización, eche un vistazo a este código:

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


}
Kmelliti
fuente
1

Todo lo que necesita hacer es anular el método getParams en la clase Request. Tuve el mismo problema y busqué las respuestas, pero no pude encontrar una adecuada. El problema es a diferencia de la solicitud de obtención, los parámetros de publicación que los servidores redirigen pueden descartarse. Por ejemplo, lea esto . Por lo tanto, no se arriesgue a que el servidor web redirija sus solicitudes. Si tiene como destino http: // example / myapp , mencione la dirección exacta de su servicio, que es http://example.com/myapp/index.php .
Voley está bien y funciona perfectamente, el problema proviene de otro lugar.

Davood Falahati
fuente
1

La función de anulación getParams funciona bien. Utiliza el método POST y ha establecido jBody como nulo. Por eso no funciona. Puede usar el método GET si desea enviar un jBody nulo. He anulado el método getParams y funciona con el método GET (y nulo jBody) o con el método POST (y jBody! = Null)

También están todos los ejemplos aquí.

usuario4292106
fuente
1

Tuve el mismo problema una vez, la matriz POST vacía se debe a una redirección de la solicitud (en el lado del servidor), corrija la URL para que no tenga que ser redirigida cuando llegue al servidor. Por ejemplo, si se fuerza https usando el archivo .htaccess en la aplicación del lado del servidor, asegúrese de que la solicitud de su cliente tenga el prefijo "https: //". Por lo general, cuando ocurre una redirección, se pierde la matriz POST. ¡Espero que esto ayude!

Pedro Emilio Borrego Rached
fuente
0

Funcionó para poder probar esto para llamar con Volley Json Request and Response con código Java.

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
        }

    }
Tarit Ray
fuente
0



build gradle (aplicación)

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

manifiesto de Android
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

MainActivity
Cuando usa JsonObjectRequest, es obligatorio enviar un jsonobject y recibir jsonobject, de lo contrario obtendrá un error ya que solo acepta 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)
}

archivo 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;
?>

archivo 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;
    }
?>
Jairo Rodríguez
fuente
¿Podrías explicar este código? En este momento, no está claro cómo esto resuelve el problema.
Ryan M