使用 Volley 库未从 Android 收到 PHP POST

Posted

技术标签:

【中文标题】使用 Volley 库未从 Android 收到 PHP POST【英文标题】:PHP POST not received from Android using Volley library 【发布时间】:2015-11-13 01:00:06 【问题描述】:

我使用 Volley 在 android 中使用以下代码发出了发布请求。

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.POST, ServerURL.URL_REGISTER, new Response.Listener<JSONObject>() 

    @Override
    public void onResponse(JSONObject response) 
        Log.d(TAG_REGISTER, "Register Response: " + response.toString());
        pDialog.dismiss();

        try 
            JSONObject jObj = new JSONObject(response.toString());
            boolean error = jObj.getBoolean("error");
            if (!error) 
                // User successfully stored in mysql
                // Now store the user in sqlite
                String uid = jObj.getString("uid");

                JSONObject user = jObj.getJSONObject("user");
                String name = user.getString("name");
                String email = user.getString("email");
                String created_at = user
                        .getString("created_at");

                // Inserting row in users table
                db.addUserIntoSQLite(name, email, uid, created_at);

                Toast.makeText(getActivity(), "User successfully registered. Try login now!", Toast.LENGTH_LONG).show();

                // Launch main activity
                Intent intent = new Intent(getActivity(), MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                getActivity().overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
                startActivity(intent);
                getActivity().finish();

             else 

                // Error occurred in registration. Get the error
                // message
                String errorMsg = jObj.getString("error_msg");
                Toast.makeText(getActivity(), errorMsg, Toast.LENGTH_LONG).show();
            
         catch (JSONException e) 
            Toast.makeText(getActivity(), "JSONException: " + e.getMessage(), Toast.LENGTH_LONG).show();
        

    
, new Response.ErrorListener() 

    @Override
    public void onErrorResponse(VolleyError error) 
        Log.e(TAG_REGISTER, "Registration Error: " + error.getMessage());
        Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
        pDialog.dismiss();
    
) 

    @Override
    public String getBodyContentType() 
        return "application/json; charset=utf-8";
    

    @Override
    protected Map<String, String> getParams() throws AuthFailureError 
        HashMap<String, String> params = new HashMap<>();
        params.put("tag", "register");
        params.put("name", name);
        params.put("email", email);
        params.put("password", password);
        return params;
    
;

现在是接收 post 请求并获取 post 值的 php 部分。

<?php
session_start();

if (!empty($_POST['tag'])) 

    // get tag
    $tag = $_POST['tag'];

    // include db handler
    require_once 'mysql/DB_Functions.php';
    $db = new DB_Functions();

    // response Array
    $response = array("tag" => $tag, "error" => FALSE);

    // check for tag type
    if ($tag == 'login') 
        // Request type is check Login
        $email = $_POST['email'];
        $password = $_POST['password'];

        // check for user
        $user = $db->getUserByEmailAndPassword($email, $password);
        if ($user != false) 
            // user found
            $response["error"] = FALSE;
            $response["uid"] = $user["unique_id"];
            $response["user"]["name"] = $user["name"];
            $response["user"]["email"] = $user["email"];
            $response["user"]["created_at"] = $user["created_at"];
            $response["user"]["updated_at"] = $user["updated_at"];
            echo json_encode($response);
         else 
            // user not found
            // echo json with error = 1
            $response["error"] = TRUE;
            $response["error_msg"] = "Incorrect email or password!";
            echo json_encode($response);
        
     else if ($tag == 'register') 
        // Request type is Register new user
        $name = $_POST['name'];
        $email = $_POST['email'];
        $password = $_POST['password'];

        // check if user is already existed
        if ($db->userExists($email)) 
            // user is already existed - error response
            $response["error"] = TRUE;
            $response["error_msg"] = "User already exists";
            echo json_encode($response);
         else 
            // store user
            $user = $db->storeUser($name, $email, $password);
            if ($user) 
                // user stored successfully
                $response["error"] = FALSE;
                $response["uid"] = $user["unique_id"];
                $response["user"]["name"] = $user["name"];
                $response["user"]["email"] = $user["email"];
                $response["user"]["created_at"] = $user["created_at"];
                $response["user"]["updated_at"] = $user["updated_at"];
                echo json_encode($response);
             else 
                // user failed to store
                $response["error"] = TRUE;
                $response["error_msg"] = "Error occured in Registartion";
                echo json_encode($response);
            
        
     else 
        // user failed to store
        $response["error"] = TRUE;
        $response["error_msg"] = "Unknow 'tag' value. It should be either 'login' or 'register'";
        echo json_encode($response);
    
 else 
    $response["error"] = TRUE;
    $response["error_msg"] = "Operation failed due to the missing tag!";
    echo json_encode($response);


var_dump($_SERVER['REQUEST_METHOD'], $_POST);
?>

我应该能够获取“标签”值,但问题是它一直说“标签”丢失。

所以现在我创建了一个 html 文件来测试哪个部分有问题。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="index.php" method="post">
Tag: <input type="text" name="tag"><br>
Name: <input type="text" name="name"><br>
Email: <input type="text" name="email"><br>
Password: <input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>

当我把数据放到这个 HTML 文件中时,数据就成功地存储在了 MySQL 数据库中。你觉得哪一部分有问题?

我已经搜索了有关 Volley 部分的所有解决方案,我的 Volley 部分似乎没有问题。所以我相信这是导致问题的 PHP 部分。

如果我在网络上打开 PHP 文件,它会显示以下消息。

"error":true,"error_msg":"Operation failed due to the missing tag!"string(3) "GET" array(0)  

【问题讨论】:

顺便说一句,如果您打算收集登录信息或其他敏感数据,请务必通过 https 进行此操作并遵循安全最佳实践。一个好的起点在这里:developer.android.com/training/best-security.html 【参考方案1】:

问题是您从 Volley 库以内容类型 application/json 发送数据,但您的 PHP 脚本期望 POST 数据作为内容类型 application/x-www-form-urlencoded。这就是为什么您的网络表单中的 POST 有效,而 Volley 中的 POST 无效。

在您的 PHP 脚本中,执行以下操作:

$data = json_decode(file_get_contents('php://input'), true);

if (empty($data['tag']) == false) 
    $tag = $data['tag'];
    echo $tag;

因为您以 JSON 格式发送数据,PHP 不会自动将其解析到 $_POST 全局变量中。上面的代码所做的是将原始的 POST 数据作为一个字符串并将其解析为一个数组。

更新

我花了一些时间调试这个,现在有了一个完整的解决方案:

PHP:

更改您的脚本以使用我上面列出的方法访问原始 POST 数据,而不是使用 $_POST 全局方法。将此代码用于调试目的:

<?php

$data = json_decode(file_get_contents('php://input'), true);

if (empty($data['tag']) == false) 
    $tag = $data['tag'];


echo json_encode([ "tag" => $tag ]);
?>

安卓

getParams() 显然没有与 JsonObjectRequest 类一起使用,所以你的身体是空的。见the answer to this question for details of that。相反,您必须在构造函数中将您的主体作为JsonObject 传递给JsonObjectRequest。例如:

    HashMap<String, String> params = new HashMap<>();
    params.put("tag", "register");
    params.put("name", "myname");
    params.put("email", "myname@email.com");
    params.put("password", "meow");
    JSONObject o = new JSONObject(params);
    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
        Request.Method.POST, 
        ServerURL.URL_REGISTER, 
        o, 
        new Response.Listener<JSONObject>()  // ... 

结果

D/示例:注册响应:"tag":"register"

我创建了一个more complete example as a gist。

注意:如果您在本地机器上向开发服务器发出请求,则需要使用10.0.2.2:PORT 而不是 localhost:PORT。我假设在您的情况下这不是问题,因为您似乎能够连接到您的服务器,但为了任何未来读者的完整性,请包含此注释。

【讨论】:

感谢您的提示。但这也没有用。它仍然说标签丢失。

以上是关于使用 Volley 库未从 Android 收到 PHP POST的主要内容,如果未能解决你的问题,请参考以下文章

未从 Android 地理围栏事件收到 Intent

如何在 Android 中使用 Volley 库进行肥皂发布请求

Android ADT 错误,dx.jar 未从 SDK 文件夹加载

如何通过 Volley Android 发布多个大图像文件

为啥我会收到“尝试导入错误:'EffectCards' 未从 'swiper' 导出”?

发送少量通知后未从 GCM 收到推送通知