User registration in Android, Java, PHP, and MySQL

User registration is used in almost every android app today.

We will create a registration form in an android application using Java. And when the form is submitted, we will send an HTTP request from android to the PHP server that will save the user’s data in the MySQL database.

MySQL table structure

Following will be the table structure for users table:

--
-- Table structure for table `users`
--

CREATE TABLE `users` (
  `id` int(11) NOT NULL,
  `name` text NOT NULL,
  `username` text NOT NULL,
  `password` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Indexes for table `users`
--
ALTER TABLE `users`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

Users table will have a unique ID that will be used to uniquely identify the user in the whole users table. We are adding a “primary key” index to the ID field. And also an “AUTO_INCREMENT” that will automatically generate the next ID number. For example, if there are 4 users already registered and a new user tries to register, then the MySQL database will automatically assign his ID to 5.

User registration in android – Layout

Now come to the android part. First, we will be creating a layout for the registration form. To keep the things simple, we are using name, username, and password in the registration form:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_login"
    android:paddingLeft="36dp"
    android:paddingTop="15dp"
    android:paddingRight="36dp">

    <ImageView
        android:id="@+id/logo"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerHorizontal="true"
        android:src="@drawable/logo" />

    <TextView
        android:id="@+id/tv_Signup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/logo"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:text="Create an account"
        android:textColor="#ffffff"
        android:textSize="20sp" />

    <EditText
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_Signup"
        android:backgroundTint="@android:color/white"
        android:hint="Full Name"
        android:inputType="text|textCapWords"
        android:maxLines="1"
        android:textColor="#ffffff"
        android:textColorHint="#ffffff" />

    <EditText
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/name"
        android:backgroundTint="@android:color/white"
        android:digits="qwertyuiopasdfghjklzxcvbnm1234567890"
        android:hint="Username"
        android:inputType="text"
        android:maxLines="1"
        android:textColor="#ffffff"
        android:textColorHint="#ffffff" />

    <android.support.v7.widget.AppCompatEditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/username"
        android:backgroundTint="@android:color/white"
        android:drawablePadding="5dp"
        android:hint="Password"
        android:inputType="textPassword"
        android:maxLines="1"
        android:textColor="#ffffff"
        android:textColorHint="#ffffff"
        android:textCursorDrawable="@null" />

    <Button
        android:id="@+id/btn_register"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_below="@+id/password"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:text="Register" />

    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn_login"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp" />
</RelativeLayout>

In android, dp – Density-independent Pixels – is an abstract unit that is based on the physical density of the screen. These units are relative to a 160 dpi screen, so one dp is one pixel on a 160 dpi screen. The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion.

  1. <RelativeLayout> it will have full width and height to the screen, has an image as background (as in the screenshot). Will have padding from left (36dp), right (36dp), and top (15dp).
  2. <ImageView> to display the logo of the app or company. It has 100dp widths and 100dp height
  3. <TextView> to display the heading of the page.
  4. <EditText> is the input field for name. It will be below the heading. Its text will be in white color. Each word will be capitalized.
  5. Second <EditText> is for username. It will be below the name field. You can only write a-z and 0-9 digits, no special characters will be allowed.
  6. <android.support.v7.widget.AppCompatEditText> this field is for password. User cannot see the text entered in this field.
  7. <Button> which when clicked will submit the form and send an HTTP request to PHP server to store that data in MySQL database.
  8. Finally a <ProgressBar> to display a loading circle when the request is sent to the server. And will be hidden when the response is received from the server.

Call HTTP request – Volley

In your app/build.gradle, make sure to add Volley dependency:

dependencies {
    ....

    implementation 'com.android.volley:volley:1.1.1'
}

Now in your register activity’s onCreate method paste the following code. We will explain that line-by-line:

ProgressBar progressBar = findViewById(R.id.progressBar);
progressBar.setVisibility(View.GONE);

EditText username = findViewById(R.id.username);
EditText password = findViewById(R.id.password);
EditText name = findViewById(R.id.name);

Button btn_register = findViewById(R.id.btn_register);
btn_register.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        String usernameText = username.getText().toString().trim();
        String passwordText = password.getText().toString().trim();
        String nameText = name.getText().toString().trim();

        if (!usernameText.isEmpty() && !passwordText.isEmpty() && !nameText.isEmpty()) {

            progressBar.setVisibility(View.VISIBLE);
            btn_register.setEnabled(false);

            String url = "http://localhost/tutorials/Http.php";
            // Instantiate the RequestQueue.
            RequestQueue queue = Volley.newRequestQueue(this);

            // Request a string response from the provided URL.
            StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
                    new Response.Listener<String>() {
                        @Override
                        public void onResponse(String response) {
                            try {
                                JSONObject responseJson = new JSONObject(response);
                                String status = responseJson.getString("status");
                                String message = responseJson.getString("message");

                                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();

                                progressBar.setVisibility(View.GONE);
                                btn_register.setEnabled(true);
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    error.printStackTrace();
                    Toast.makeText(getApplicationContext(), error.getLocalizedMessage(), Toast.LENGTH_LONG).show();
                }
            }) {
                @Override
                protected Map<String, String> getParams() {
                    Map<String, String> params = new HashMap<>();
                    params.put("name", name.getText().toString().trim());
                    params.put("username", username.getText().toString().trim());
                    params.put("password", password.getText().toString().trim());
                    params.put("registration", "1");

                    return params;
                }

                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> params = new HashMap<>();
                    params.put("Content-Type", "application/x-www-form-urlencoded");
                    return params;
                }
            };

            // To prevent timeout error
            stringRequest.setRetryPolicy(new DefaultRetryPolicy(50000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

            // Add the request to the RequestQueue.
            stringRequest.setShouldCache(false);
            queue.add(stringRequest);

        } else {
            Toast.makeText(getApplicationContext(), "Please fill all details", Toast.LENGTH_LONG).show();
        }
    }
});
  1. First, we are creating an instance of ProgressBar and hiding it by default. We will only display when the request is sent.
  2. Then we are getting the name, username, and password input fields objects.
  3. After that, we are checking if any of the fields are empty, then display an error in Toast.
  4. Now, we are displaying the progress bar and disabling register button, so the user cannot click multiple times.
  5. Then we are sending a request using Volley. The request method should be POST.
  6. getParams() will have all our parameters. We are sending a name, username, and password along with an additional value “registration” that will be used to tell the server to handle the request for registration.
  7. Response received from the server will be a JSON string, so we are converting that into JSONObject, and displaying server response message in a Toast.
  8. And finally, we are hiding the progress bar and enable the register button again. So if there is any error, then the user can click on the register button again.

Save user data in MySQL using PHP

Now come to the server-side. As you see we are sending the request to Http.php so we must have that file in our server. This file should have the following content, we will explain that line-by-line:

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$conn = mysqli_connect("localhost", "root", "root", "tutorials");

if (isset($_POST["registration"]))
{
    $username = $_POST["username"];
    $name = $_POST["name"];

    $sql = "SELECT * FROM `users` WHERE `username` = '" . $username . "'";
    $result = mysqli_query($conn, $sql);

    if (mysqli_num_rows($result) > 0)
    {
        echo json_encode(array(
            "status" => "error",
            "message" => "Username already exists"
        ));
        exit();
    }

    $password = password_hash($_POST["password"], PASSWORD_DEFAULT);

    $sql = "INSERT INTO `users`(`name`, `username`, `password`) VALUES ('" . $name . "', '" . $username . "', '" . $password . "')";
    mysqli_query($conn, $sql);

    echo json_encode(array(
        "status" => "success",
        "message" => "Account has been created",
        "user_id" => mysqli_insert_id($conn) . ""
    ));
    exit();
}
  1. First, we are enabling all PHP errors. So if there is any error it will be received in error response in the android app.
  2. Then we are connecting with the database using host: port, username, password, and database name respectively.
  3. After that, we are checking if the request received is for registration, then get the name, username, and password fields from a POST request.
  4. Now, check from the database if the user with the same username already exists in the user’s table, if yes, then send an error response and stop the script using exit() function.
  5. Then convert the plain text password into an encrypted hash, so even if your database got hacked, no one will know the actual password of your users.
  6. And finally, run an INSERT query to save the database in MySQL database and send the success response back to the android app.
  7. We are also sending the inserted ID in response. So if you want to use the newly inserted ID in the MySQL table, you can get it from mysqli_insert_id function and passing the connection as a parameter.

User registration has been done in your android project. You can also learn how to authenticate the user for login and save his data in android Shared Preferences.