具有Volley和PHP的Android JSON在字符0处输入结束
I am writing an app that requires the use of storing contacts in a database so I am using wammp and PHPMyAdmin to write a simple REST API. I have written the parts that involve registering and logging in but for some reason I can not get the storing of contacts to work even though I thought it would be almost the same thing verbatim. I am getting the exception:
org.json.JSONException: End of input at character 0 of
I have looked around all over for this issue and it looks to be like the JSON that I am passing back to my app is empty, so I am aware of the problem but everywhere that I looked, the solutions did not help me actually fix the problem so I feel like it may be a unique problem. Here is my relevant Android code:
// Create the new string request
StringRequest stringRequest = new StringRequest(Request.Method.POST, AppConfig.URL_NEW_CONTACT, new Response.Listener<String>()
{
@Override
public void onResponse(String response)
{
// Log method entry
MethodLogger methodLogger = new MethodLogger();
// Log the JSON that was returned
methodLogger.d("New Contact Response: " + response.toString());
// Remove the processing view
hideDialog();
// Try to retrieve JSON and parse through it
try
{
JSONObject jObj = new JSONObject(response);
// Check for errors in the JSON passed back
boolean error = jObj.getBoolean("error");
/*----------------------------------------------------------------*
* If there was no error found *
*----------------------------------------------------------------*/
if (!error)
{
// Indicate the success to the user
Toast.makeText(getApplicationContext(), "Contact successfully created.", Toast.LENGTH_LONG).show();
// Take the user back to the contact page
routeToContactPage();
}
/*----------------------------------------------------------------*
* Else if there was an error found *
*----------------------------------------------------------------*/
else
{
// Notify the user
String errorMsg = jObj.getString("message");
Toast.makeText(getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
}
/*--------------------------------------------------------------------*
* Catch any error in retrieving parsing etc JSON *
*--------------------------------------------------------------------*/
catch (JSONException e)
{
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Error storing contact: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
// Log method exit
methodLogger.end();
}
}, new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error)
{
// Log method entry
MethodLogger methodLogger = new MethodLogger();
// Notify the user
methodLogger.e("Error storing contact: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
hideDialog();
// Log method exit
methodLogger.end();
}
})
{
@Override
protected Map<String, String> getParams()
{
// Log method entry
MethodLogger methodLogger = new MethodLogger();
// create a new params object and add the contact data
Map<String, String> params = new HashMap<String, String>();
// Add the params to the volley request
params.put("user_id", SessionManager.getUser().getId());
params.put("name", name);
params.put("email", emailAddress);
// Log method exit
methodLogger.end();
// Return the user data
return params;
}
};
// Send the request string to the request queue to be sent to the PHP API
AppController.getInstance().addToRequestQueue(stringRequest, tag_string_req);
}
Relevant PHP Code:
Store the contact:
public function storeContact($name, $email, $user_id)
{
$uuid = uniqid('', true);
$result = mysqli_query($this->conn, "INSERT INTO contacts (unique_id, name, email, created_at, updated_at, user_id) VALUES ('$uuid', '$name', '$email', NOW(), NULL, '$user_id')") or die (mysql_error());
if ($result)
{
$contact = mysqli_query($this->conn, "SELECT * FROM contacts WHERE name = '$name' AND user_id = '$user_id'");
return $contact;
}
else
{
return false;
}
}
Communicate with the server/app:
<?php
require_once 'include/DB_Functions.php';
$db = new DB_Functions();
$response = array();
if (isset($_POST['user_id']) && isset($_POST['name']) && isset($_POST['email']))
{
$user_id = $_POST['user_id'];
$name = $_POST['name'];
$email = $_POST['email'];
$result = $db->storeContact($name, $email, $user_id);
if ($result)
{
$response["error"] = FALSE;
$response["message"] = "Contact stored successfully";
}
else
{
$response["error"] = TRUE;
$response["message"] = "Unknown error occurred in storing contact";
}
}
else
{
$response["error"] = TRUE;
$response["message"] = "Required parameters, name, email, or user_id, missing";
}
echo json_encode($response);
?>
and finally, relevant logcat output:
07-30 22:39:07.408 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.AppController: Method Entry: getInstance()
getInstance() finished in 0.000 seconds.
Method Entry: addToRequestQueue()
07-30 22:39:07.409 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.AppController: Method Entry: getRequestQueue()
getRequestQueue() finished in 0.000 seconds.
07-30 22:39:07.410 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.AppController: addToRequestQueue() finished in 0.001 seconds.
07-30 22:39:07.410 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.ContactActivity: onCreate() finished in 0.072 seconds.
07-30 22:39:07.424 24212-31569/com.example.e4977.spotme D/com.example.e4977.spotme.ContactActivity$3: Method Entry: getParams()
07-30 22:39:07.425 24212-31569/com.example.e4977.spotme D/com.example.e4977.spotme.ContactActivity$3: getParams() finished in 0.000 seconds.
07-30 22:39:07.426 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.NewContactActivity$1$1: Method Entry: onResponse()
onResponse() New Contact Response:
07-30 22:39:07.426 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.NewContactActivity: Method Entry: hideDialog()
07-30 22:39:07.448 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.NewContactActivity: hideDialog() finished in 0.021 seconds.
07-30 22:39:07.448 24212-24212/com.example.e4977.spotme W/System.err: org.json.JSONException: End of input at character 0 of
at org.json.JSONTokener.syntaxError(JSONTokener.java:449)
at org.json.JSONTokener.nextValue(JSONTokener.java:97)
at org.json.JSONObject.<init>(JSONObject.java:159)
at org.json.JSONObject.<init>(JSONObject.java:176)
at com.example.e4977.spotme.NewContactActivity$1$1.onResponse(NewContactActivity.java:119)
07-30 22:39:07.449 24212-24212/com.example.e4977.spotme W/System.err: at com.example.e4977.spotme.NewContactActivity$1$1.onResponse(NewContactActivity.java:99)
at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6798)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
07-30 22:39:07.454 24212-24212/com.example.e4977.spotme D/com.example.e4977.spotme.NewContactActivity$1$1: onResponse() finished in 0.027 seconds.
Its also worth it to note that I see that the response is empty, I however do not know why. Here is the Database Schema in case that is part of the problem too.
Answer
I'm fairly sure the reason for this is that you are using the mysqli_*
set of functions but then attempting to get the latest error text using mysql_error
, which will return an empty string as there have been no errors from calls to mysql_*
functions.
Try replacing:
$result = mysqli_query($this->conn, /* the rest */) or die (mysql_error());
with:
$result = mysqli_query($this->conn, /* the rest */) or die (mysqli_error($this->conn));
You'll still get an exception thrown, similar to:
org.json.JSONException: Value Data of type java.lang.String cannot be converted to JSONObject
because the response will not be valid JSON, but this should help you on your way.
Side note
Because it's such a classic issue, I can't avoid commenting on the SQL injection issue in the code you've posted. It's worth having a read through https://cwe.mitre.org/data/definitions/89.html to understand the issue, and then taking a look at http://php.net/manual/en/mysqli.quickstart.prepared-statements.php for how to put together a safer implementation using mysqli_prepare
, mysqli_stmt_bind_param
and mysqli_stmt_execute
.