使用POST方法和HttpURLConnection从Android向PHP服务器发送JSON对象

7
我正在尝试在本地网络中建立我的Android应用和WampServer之间的通信。当我想从服务器读取数据时,已经成功了,但是当我尝试向服务器发送数据时出现问题。我使用服务来建立通信:
public class SynchronisationService extends Service {
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);

    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                URL url = new URL("http://192.168.37.23/happiness_barometer/php_input.php");
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setDoOutput(true);
                connection.setDoInput(false);
                connection.setRequestMethod("POST");
                connection.connect();
                OutputStream outputStream = connection.getOutputStream();
                OutputStreamWriter writer = new OutputStreamWriter(outputStream);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("rate", 1);
                writer.write(URLEncoder.encode(jsonObject.toString(), "UTF-8"));
                writer.flush();
                writer.close();

            } catch (Exception e) {
                Log.v("EXCEPTION", e.getMessage());
            }
        }
    }).start();


    stopSelf();

    return flags;
}

而我的PHP文件:

 <?php 

    try 
    {
        $bdd = new PDO('mysql:host=localhost;dbname=happiness_barometer;charset=utf8', 'utilisateur', '');
    } catch (Exception $e) 
    {
        die('Erreur : '.$e->getMessage());
    }

    $sql = $bdd->prepare(
    'INSERT INTO rates (rate, comment, category, day, month, year, hour, minute, day_of_week, week, rate_number) 
    VALUES (:rate, :comment, :category, :day, :month, :year, :hour, :minute, :day_of_week, :week, :rate_number)');
    if (!empty($_POST['rate'])) {
        $sql->execute(array(
            'rate' => $_POST['rate'],
            'comment' => '',
            'category' => 'pro',
            'day' => 19,
            'month' => 8,
            'year' => 2015,
            'hour' => 18,
            'minute' => 3,
            'day_of_week' =>3,
            'week' => 33,
            'rate_number' => 2));
    }
?>

当我运行我的应用程序时,没有任何东西被添加到我的数据库中。我认为 $_POST['rate'] 中没有内容。
请告诉我代码有什么问题?

你能否发布你的堆栈跟踪(Logcat)? - vinay Maneti
@vinay Maneti:我的logcat里大约有200行。哪些行是重要的? - Anaïs
与您的SynchronisationService和activity类相关的编程内容。 - vinay Maneti
没有与SynchronisationService相关的行...(很抱歉,我只是在异常发生时使用logcat查看) - Anaïs
2个回答

18

最终,我成功将一个JSONObject发送到了我的服务器。

我在Android部分使用了以下代码:

new Thread(new Runnable() {
        @Override
        public void run() {
            OutputStream os = null;
            InputStream is = null;
            HttpURLConnection conn = null;
            try {
                //constants
                URL url = new URL("http://192.168.43.64/happiness_barometer/php_input.php");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("rate", "1");
                jsonObject.put("comment", "OK");
                jsonObject.put("category", "pro");
                jsonObject.put("day", "19");
                jsonObject.put("month", "8");
                jsonObject.put("year", "2015");
                jsonObject.put("hour", "16");
                jsonObject.put("minute", "41");
                jsonObject.put("day_of_week", "3");
                jsonObject.put("week", "34");
                jsonObject.put("rate_number", "1");
                String message = jsonObject.toString();

                conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout( 10000 /*milliseconds*/ );
                conn.setConnectTimeout( 15000 /* milliseconds */ );
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);
                conn.setFixedLengthStreamingMode(message.getBytes().length);

                //make some HTTP header nicety
                conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
                conn.setRequestProperty("X-Requested-With", "XMLHttpRequest");

                //open
                conn.connect();

                //setup send
                os = new BufferedOutputStream(conn.getOutputStream());
                os.write(message.getBytes());
                //clean up
                os.flush();

                //do somehting with response
                is = conn.getInputStream();
                //String contentAsString = readIt(is,len);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            } finally {
                //clean up
                try {
                    os.close();
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                conn.disconnect();
            }
        }
    }).start();

还有一个在 PHP 部分的:

$json = file_get_contents('php://input');
$obj = json_decode($json);
$rate = $obj->{'rate'};
$comment = $obj->{'comment'};
$category = $obj->{'category'};
$day = $obj->{'day'};
$month = $obj->{'month'};
$year = $obj->{'year'};
$hour = $obj->{'hour'};
$minute = $obj->{'minute'};
$day_of_week = $obj->{'day_of_week'};
$week = $obj->{'week'};
$rate_number = $obj->{'rate_number'};

try 
{
    $bdd = new PDO('mysql:host=localhost;dbname=happiness_barometer;charset=utf8', 'utilisateur', '');
} catch (Exception $e) 
{
    die('Erreur : '.$e->getMessage());
}

$sql = $bdd->prepare(
'INSERT INTO rates (rate, comment, category, day, month, year, hour, minute, day_of_week, week, rate_number) 
VALUES (:rate, :comment, :category, :day, :month, :year, :hour, :minute, :day_of_week, :week, :rate_number)');
if (!empty($rate)) {
    $sql->execute(array(
        'rate' => $rate,
        'comment' => $comment,
        'category' => $category,
        'day' => $day,
        'month' => $month,
        'year' => $year,
        'hour' => $hour,
        'minute' => $minute,
        'day_of_week' => $day_of_week,
        'week' => $week,
        'rate_number' => $rate_number));
}

希望它能帮助其他人 ;)


@Anaïs 我正在使用相同的代码,我得到的响应是httpUrlConnection.getResponse()为HttpURLConnection.HTTP_OK,但是php不接受json数据。请帮忙。 - Yirga
你将os声明为OutputStream,但却将其赋值为BufferedOutputStream。不确定你使用的是哪个API,但在当前版本中它不会起作用。 - Pavel
你好。我尝试了你的代码,但是没有显示任何内容。请帮帮我。.php文件有问题吗? - Ali Hosein pour

1

使用此代码进行检查:

public class UniversalNetworkConnection {

    public static String postJSONObject(String myurl, JSONObject parameters) {
        HttpURLConnection conn = null;
        try {
            StringBuffer response = null;
            URL url = new URL(myurl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(15000);
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            OutputStream out = new BufferedOutputStream(conn.getOutputStream());
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
            writer.write(parameters.toString());
            writer.close();
            out.close();
            int responseCode = conn.getResponseCode();
            System.out.println("responseCode" + responseCode);
            switch (responseCode) {
                case 200:
                    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    String inputLine;
                    response = new StringBuffer();
                    while ((inputLine = in.readLine()) != null) {
                        response.append(inputLine);
                    }
                    in.close();
                    return response.toString();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.disconnect();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
        return null;
    }

}

在PHP方面:
<?php
    $json = file_get_contents('php://input');
    $obj = json_decode($json);
    print_r($obj);
    print_r("this is a test");
?>

我尝试了这段代码,但什么也没有发生:没有异常,没有错误,在logcat中也没有System.out的任何信息。 - Anaïs
@Anaïs 检查wamp->apache->访问日志。检查连接是否已建立。 - Bonatti
@Bonatti,我检查了访问日志,发现php_output文件被本地网络上的客户端(IP地址:192.168.36.212)“打开”,但是php_input文件从未被“打开”。我还发现了一个408错误。这有帮助吗? - Anaïs
@Anaïs 408错误很可能是服务器在期望请求时没有收到完整的请求。请使用cURL或其他方法从不同的源执行请求,以排除服务器端的任何故障。如果您没有从服务器收到错误,则表示您的Android设备缺少请求部分...至少包括“Content-Type”、“Content-Length”和“charset”。 - Bonatti
@Harsha,这听起来像是外包! - Skynet
@Skynet,我没有错误,并且我检查了访问日志,连接已经建立并从服务器获得了200响应,但是PHP脚本无法读取JSON数据。 - Yirga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接