0

I am using PHP as my API for a messaging android app, I have created a script which will register the user by inserting data into the database when logging for the first time, I have tried this Link but my primary key is unique and still the script is executing two times and which causes an error :-

[27-Feb-2018 17:44:12 UTC] PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '3bc91dab47aeb989' for key 'users_device_id_uindex'' in [My Api Url]/DbFunction.php:44

Which means that there is a duplicate entry in the table.Basically, It stores the value perfectly when executed for the first time but when it executes again it gives the error described above

Script for registration (register.php):-

<?php
require_once ("DbFunction.php");//Importing DbFunction Class

/*Initializing Variables*/
$response = array();
$db = new DbFunction();
$result = $device_id = $phone_number = $user_name = $email = $website = 
$profile_picture = $token = $created_at = '';

/* Checking If REQUEST_METHOD is POST*/
if($_SERVER['REQUEST_METHOD'] == 'POST') {

/*Checking is variables are set*/
  $device_id = isset($_POST['device_id']) ? $_POST['device_id']:null;
  $phone_number = isset($_POST['phone_number']) $_POST['phone_number']:null;
  $user_name = isset($_POST['user_name']) ? $_POST['user_name'] : null;
  $email = isset($_POST['email']) ? $_POST['email'] : null;
  $website = isset($_POST['website']) ? $_POST['website'] : null;
  $profile_picture = isset($_POST['profile_picture']) ? $_POST['profile_picture'] : null;
  $token = isset($_POST['token']) ? $_POST['token'] : null;
  $created_at = isset($_POST['created_at']) ? $_POST['created_at'] : null;


 /* Checking For Nulls*/
if (!isNull($device_id) || !isNull($phone_number) || !isNull($user_name) || !isNull($email) || !isNull($profile_picture) || !isNull($token) || !isNull($created_at)) {

        /* Calling The createUser functions with required parameters*/
        $result = $db->createUser($device_id, $phone_number, $user_name, $email, $website, $profile_picture, $token, $created_at);
        $response['error'] = !$result;// Setting the value of error which is inverse of $result(if result == true which means user registered successfully and there is no error so inverse of result which is false and vice versa)
        if($result)
        {
            $response['message'] = "User Registered Successfully";
        }
        else{
            $response['message'] = "Registration Error";
        }
    }
   /* Echoing The Reponse*/
    echo json_encode($response);
}
function isNull($variable)
{
    return is_null($variable);
}

script for functions (DbFunction.php):-

 public function createUser($device_id,$phone_number,$user_name ,$email ,$website ,$profile_dp ,$token ,$created_at )
{
        /* Calling the uploadImage funtion to upload the Image To Server which will Return Url Where Image Is Stored*/
        $profile_picture = $this->uploadImage($profile_dp, $email);

        $stmt = $this->conn->prepare("INSERT INTO users (device_id, phone_number, user_name, email, website, profile_picture, token, created_at) VALUES (:device_id, :phone_number, :user_name, :email, :website, :profile_picture, :token, :created_at)");
        $stmt->bindValue(':device_id', $device_id);
        $stmt->bindValue(':phone_number', $phone_number);
        $stmt->bindValue(':user_name', $user_name);
        $stmt->bindValue(':email', $email);
        $stmt->bindValue(':website', $website);
        $stmt->bindValue(':profile_picture', $profile_picture);
        $stmt->bindValue(':token', $token);
        $stmt->bindValue(':created_at', $created_at);
       return $stmt->execute();
}

And now the Android code from where I am calling the request, I am using volley for that.

UserInfoActivity.java :-

 @Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.btnNext:
            if (isValidInput()) {
                sendDataToServer();
                dialog.setMessage("Loading....");
                dialog.show();
            }
    }
}




private void sendDataToServer() {
    StringRequest strreq = new StringRequest(Request.Method.POST,
            Config.URL_REGISTER,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String Response) {
                    dialog.dismiss();
                    Log.d(TAG, Response);
                    Boolean error = null;
                    JSONObject jsonObject = null;
                    try {
                        jsonObject = new JSONObject(Response);
                        error = jsonObject.getBoolean("error");
                        if(!error)
                        {
                            Toast.makeText(UserInfoActivity.this,"User Registered Successfully",Toast.LENGTH_LONG).show();
                        }
                        else {
                            Toast.makeText(UserInfoActivity.this, "Something Went Wrong While Registering", Toast.LENGTH_LONG).show();
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                        Toast.makeText(UserInfoActivity.this, "Something Went Wrong While Registering", Toast.LENGTH_LONG).show();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError e) {
            VolleyLog.e(TAG, e);
            e.printStackTrace();
            Toast.makeText(UserInfoActivity.this, "Something Went Wrong While Registering", Toast.LENGTH_LONG).show();
            dialog.dismiss();
        }
    }) {
        @SuppressLint("HardwareIds")
        @Override
        public Map<String, String> getParams() {
            DateTime dateTime = new DateTime();
            SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
            Map<String, String> params = new HashMap<>();
            params.put("phone_number", FirebaseAuth.getInstance().getCurrentUser().getPhoneNumber());
            params.put("user_name", etName.getText().toString());
            params.put("email", etEmail.getText().toString());
            if (!TextUtils.isEmpty(etWebsite.getText().toString())) {
                params.put("website", etWebsite.getText().toString());
            }
            params.put("token", pref.getString("token", null));
            params.put("device_id",  Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID));
            params.put("created_at", dateTime.toString());
            params.put("profile_picture", image_to_server);
            return params;
        }
    };
    AppSingleton.getInstance(UserInfoActivity.this).addToRequestQueue(strreq);
}

AppSingleton.java :-

public class AppSingleton {
private static AppSingleton mInstance;
private RequestQueue mRequestQueue;
private static Context mContext;

private AppSingleton(Context context){
    // Specify the application context
    mContext = context;
    // Get the request queue
    mRequestQueue = getRequestQueue();
}

public static synchronized AppSingleton getInstance(Context context){
    // If Instance is null then initialize new Instance
    if(mInstance == null){
        mInstance = new AppSingleton(context);
    }
    // Return MySingleton new Instance
    return mInstance;
}

public RequestQueue getRequestQueue(){
    // If RequestQueue is null the initialize new RequestQueue
    if(mRequestQueue == null){
        mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext());
    }

    // Return RequestQueue
    return mRequestQueue;
}

public<T> void addToRequestQueue(Request<T> request){
    // Add the specified request to the request queue
    getRequestQueue().add(request);
}

}

And after request, I get an error response which is null:-

02-28 14:58:20.690 14606-14606/com.dev.pigeon E/Volley: [1] 3.onErrorResponse: USERINFOACTIVITYTAG

UPDATE After Watching the Log clearly I saw this:-

02-28 17:21:36.448 21212-21815/com.dev.pigeon D/Volley: [22348] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://[My Api Url]/register.php 0xec86a58c NORMAL 1> [lifetime=8562], [size=1208], [rc=500], [retryCount=1]

02-28 17:21:36.449 21212-21815/com.dev.pigeon E/Volley: [22348] BasicNetwork.performRequest: Unexpected response code 500 for http://[My APi Url]/register.php

02-28 17:21:36.463 21212-21212/com.dev.pigeon E/Volley: [1] 3.onErrorResponse: USERINFOACTIVITYTAG

Above Error Says That Volley Is Retrying The Request, I don't know why?

Please help from where this error is occurring, I am working on this weird behavior of Volley for a long time but didn't get any solution.

P.S. Sorry For My Bad English And Badly Written Code!!

Pigeon App
  • 79
  • 1
  • 1
  • 8
  • You need to log the raw http response into the console in your android app. Android is giving you that error response because it cannot parse the response from the server. It's not really a great way to debug. If you saw what the actual message was from the server it would make it alot easier to know what exactly the error is in the database without having to check server logs. – Josh Woodcock Feb 28 '18 at 09:54
  • @Kaddath Ok This Will Solve My Problem But Why The Script Is Executing Two Times? – Pigeon App Feb 28 '18 at 09:58
  • yes, sorry, seems i strangely overlooked this part of the question, better adress the cause rather than the consequence, i'll take a look. Do you know if it is the request that is made twice, or the row insertion? – Kaddath Feb 28 '18 at 10:09
  • @PigeonApp Volley is set to auto retry if it receives a non-200 response code https://github.com/google/volley/blob/master/src/main/java/com/android/volley/DefaultRetryPolicy.java – Josh Woodcock Feb 28 '18 at 10:11
  • @Kaddath No request is not made twice anywhere, and the row insertion is also called only 1 time, You can see the codes above. – Pigeon App Feb 28 '18 at 10:17
  • @JoshWoodcock Is there any way to log the raw response while using Volley? – Pigeon App Feb 28 '18 at 10:18
  • @PigeonApp check this answer https://stackoverflow.com/questions/21867929/android-how-handle-message-error-from-the-server-using-volley – Josh Woodcock Feb 28 '18 at 10:20
  • @JoshWoodcock Please Do Watch My Updated Log. – Pigeon App Feb 28 '18 at 11:59
  • @PigeonApp yea as it shows you are getting 500 and it is retrying 1 time causing the script to execute 2 times. If I was you I would first get the request working in something like postman and then connect it to my Android app. Also its highly likely this will happen again as network activity is unreliable. You need to change your insert query to INSERT IGNORE just incase it does run more than once. – Josh Woodcock Feb 28 '18 at 12:04
  • @JoshWoodcock I Have No Idea About INSERT IGNORE, can you help on it? – Pigeon App Feb 28 '18 at 12:06
  • @PigeonApp change "INSERT INTO users ..." to "INSERT IGNORE INTO users ..." Are you deleting the user before you run this each time? – Josh Woodcock Feb 28 '18 at 12:09
  • @JoshWoodcock Ok, Yes I Am Executing This Code In The Console `TRUNCATE users;` – Pigeon App Feb 28 '18 at 13:02

0 Answers0