Volley JsonObjectRequest Post-Anfrage funktioniert nicht

78

Ich benutze Android Volley für eine Anfrage. Also benutze ich diesen Code. Ich verstehe eins nicht. Ich überprüfe auf meinem Server, dass params immer null ist. Ich denke, dass getParams () nicht funktioniert. Was soll ich tun, um dieses Problem zu lösen?

 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
quelle
5
Danke für deine Frage. Ich habe auch Probleme mit JsonObjectRequest. Also benutze ich einfach normale StringRequest. Dann hat es funktioniert. Es scheint Volleyball. Darf ich wissen, wie Sie das gelöst haben?
Thein
Ja natürlich. Sie müssen Ihre CustomJsonObjectRequest wie hier erstellen stackoverflow.com/questions/19837820/…
pmb
Danke für die Nachfrage! Ich habe das gleiche Problem auch ..
Bala Vishnu
1
weil der 3. Parameter Ihres Konstruktors null ist.
NJZK2
@ njzk2: Ich denke, pmb versucht, eine POST-Anfrage mit URL-codierten Parametern zu senden, nicht mit einem JSON-Body, wofür das dritte Argument ist. Die Antwort von LOG_TAG scheint die am besten geeignete zu sein: eine benutzerdefinierte Klasse, die Parameter akzeptiert und dennoch eine JSON-Antwort zulässt.
12.17

Antworten:

134

Versuchen Sie, diese Hilfsklasse zu verwenden

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

Verwenden Sie dies in Aktivität / Fragment

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

requestQueue.add(jsObjRequest);
LOG_TAG
quelle
1
Thx es funktioniert! Warum funktioniert das Überschreiben von getParams () in JsonObjectRequest nicht? Ist es Volley Bug?
Thein
1
Dies ist kein Fehler. GetParams () wird nicht aufgerufen, da JsonObjectRequest JsonRequest erweitert hat, wodurch getBody () direkt aufgerufen wird , um den zweiten Konstruktorparameter (call requestBody) als contentType zu codieren. Deshalb wird Ihre getParam () -Methode ignoriert.
VinceStyling
1
@LOG_TAG was ist das.createRequestSuccessListener (), this.createRequestErrorListener ()); Ich verstehe es nicht, bitte erklären Sie.
Ik024
2
@Droider Dies sind Methoden, mit denen die richtigen Objekte für die Antwortbehandlung erstellt werden. Höchstwahrscheinlich handelt es sich um einzelne Methoden zum Zwecke der Lesbarkeit. Sie können die Objekte genauso gut mit dem newSchlüsselwort erstellen , aber je nach Größe des Codes für diese Objekte kann es schwierig sein, sie auf einen Blick zu lesen.
jnfjnjtj
2
Ich hatte viele Probleme, und das funktioniert gut: D danke
Javier
29

Sie können eine benutzerdefinierte Methode erstellen JSONObjectReuqestund die getParamsMethode überschreiben oder sie im Konstruktor als JSONObjectin den Hauptteil der Anforderung einzufügen.

So (ich habe Ihren Code bearbeitet):

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
quelle
schön und schnell! aber wenn du x-www-urlencoded brauchst, wird es per Volley gemacht?
Poutrathor
Ich bin nicht sicher, aber Sie können es leicht testen.
Itai Hanski
Sind Sie sicher, dass getParams nicht aufgerufen wird? Im Gegenteil, der Code zeigt, dass er von getBody () und getPostParams () aufgerufen wird, und Sie sagen sich hier das Gegenteil: stackoverflow.com/questions/18484647/…
Poutrathor
Du hast recht, ich habe mich zwischen den Methoden verwechselt (nicht genug Schlaf). Ich habe meine Antwort bearbeitet.
Itai Hanski
versucht mit POST und GET Methode. beide funktionieren nicht. Ich habe keine Ahnung.
Amir Fazwan
5

Einfach für mich! Ich habe es vor ein paar Wochen bekommen:

Dies gilt getBody()nicht getParams()für eine Post-Anfrage.

Hier ist mein :

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

}

(Ich nahm an, dass Sie die Parameter, die Sie in Ihren getParams geschrieben haben, veröffentlichen möchten.)

Ich habe die Parameter für die Anforderung im Konstruktor angegeben, aber da Sie die Anforderung im laufenden Betrieb erstellen, können Sie sie in Ihrer Überschreibung der Methode getBody () fest codieren.

So sieht mein Code aus:

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

und wenn Sie noch mehr wollen, kommen diese letzten String- Parameter von:

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

und der paramasJObj ist ungefähr so: {"id"="1","name"="myname"}der übliche JSON-String.

Poutrathor
quelle
Ich verstehe nicht, wie man hier Parameter übergibt. String s = neuer String (param). Was ist es?
PMB
Es ist nur eine Zeichenfolge mit meinen Params dort. Ich sende es im Konstruktor. Ich werde dir noch mehr zeigen.
Poutrathor
Vielen Dank an @poutrathor, wenn Sie mir sagen können, wie ich diese Parameter in der Methode getParams () senden soll.
PMB
Ah. Sie möchten sie also als Parameter verwenden. Was postest du neugierig auf deinem Server?
Poutrathor
Mein Ziel ist es, dass ich Parameter senden muss, wie sie in getParams geschrieben wurden. Ich kann dort kein jsonObject senden.
PMB
3

Wenn Sie mit einer JsonObject-Anforderung arbeiten, müssen Sie die Parameter direkt nach dem Übergeben des Links in der Initialisierung übergeben. Sehen Sie sich diesen Code an:

        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
quelle
1

Sie müssen lediglich die Methode getParams in der Request-Klasse überschreiben. Ich hatte das gleiche Problem und suchte die Antworten durch, konnte aber keine richtige finden. Das Problem ist im Gegensatz zu get request, dass Post-Parameter, die von den Servern umgeleitet werden, möglicherweise gelöscht werden. Lesen Sie dies zum Beispiel . Riskieren Sie also nicht, dass Ihre Anfragen vom Webserver umgeleitet werden. Wenn Sie auf http: // example / myapp abzielen , geben Sie die genaue Adresse Ihres Dienstes an, nämlich http://example.com/myapp/index.php .
Volley ist in Ordnung und funktioniert perfekt, das Problem kommt von woanders her.

Davood Falahati
quelle
1

Die Override-Funktion getParams funktioniert einwandfrei. Sie verwenden die POST-Methode und haben den jBody auf null gesetzt. Deshalb funktioniert es nicht. Sie können die GET-Methode verwenden, wenn Sie null jBody senden möchten. Ich habe die Methode getParams überschrieben und sie funktioniert entweder mit der GET-Methode (und null jBody) oder mit der POST-Methode (und jBody! = Null).

Auch gibt es alle Beispiele hier

user4292106
quelle
1

Ich hatte das gleiche Problem einmal, das leere POST-Array wird durch eine Umleitung der Anforderung (auf Ihrer Serverseite) verursacht. Korrigieren Sie die URL, damit sie nicht umgeleitet werden muss, wenn sie auf den Server trifft. Wenn beispielsweise https unter Verwendung der .htaccess-Datei auf Ihrer serverseitigen App erzwungen wird, stellen Sie sicher, dass Ihre Clientanforderung das Präfix "https: //" hat. Wenn eine Umleitung stattfindet, geht normalerweise das POST-Array verloren. Ich hoffe das hilft!

Pedro Emilio Borrego Rached
quelle
0

Es hat funktioniert, kann dies versuchen, um mit Volley Json Request and Response mit Java Code anzurufen.

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
quelle
0



Gradle bauen (App)

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 Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Hauptaktivität
Wenn Sie JsonObjectRequest verwenden, müssen Sie unbedingt ein jsonobject senden und jsonobject empfangen. Andernfalls wird eine Fehlermeldung angezeigt, da nur jsonobject akzeptiert wird.
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)
}

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

Datei 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 Rodriguez
quelle
Könnten Sie diesen Code erklären? Im Moment ist es ein bisschen unklar, wie dies das Problem löst.
Ryan M
bereit Freund, den Sie sehen können
Jairo Rodriguez