1
\$\begingroup\$

This is a follow-up question for Android APP User class implementation. I am attempting to build a user registering system and this post shows the user registration page implementation.

The experimental implementation

  • Project name: UserRegistrationAPP

  • birthday.xml Layout file:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
      <path
          android:pathData="M19.313,5.097h-3.375L15.938,4h-1.125v1.097h-2.25L12.563,4L11.437,4v1.097h-2.25L9.187,4L8.062,4v1.097L4.687,5.097C3.757,5.097 3,5.835 3,6.742v12.613C3,20.262 3.757,21 4.687,21h14.626c0.93,0 1.687,-0.738 1.687,-1.645L21,6.742c0,-0.907 -0.757,-1.645 -1.687,-1.645zM19.875,19.355c0,0.302 -0.253,0.548 -0.562,0.548L4.687,19.903c-0.31,0 -0.562,-0.246 -0.562,-0.548L4.125,6.742c0,-0.303 0.252,-0.548 0.562,-0.548h3.375L8.062,7.29h1.125L9.187,6.194h2.25L11.437,7.29h1.126L12.563,6.194h2.25L14.813,7.29h1.125L15.938,6.194h3.375c0.31,0 0.562,0.245 0.562,0.548v12.613z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
      <path
          android:pathData="M7,9h2.222v1.142L7,10.142L7,9zM10.889,9h2.222v1.142L10.89,10.142L10.89,9zM14.778,9L17,9v1.142h-2.222L14.778,9zM7,12.429h2.222L9.222,13.57L7,13.57L7,12.43zM10.889,12.429h2.222L13.111,13.57L10.89,13.57L10.89,12.43zM14.778,12.429L17,12.429L17,13.57h-2.222L14.778,12.43zM7,15.857h2.222L9.222,17L7,17v-1.143zM10.889,15.857h2.222L13.111,17L10.89,17v-1.143zM14.778,15.857L17,15.857L17,17h-2.222v-1.143z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
    </vector>
    
  • email.xml Layout file:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
      <path
          android:pathData="M21.167,20.16L2.833,20.16C1.823,20.16 1,19.353 1,18.36L1,7.56C1,6.567 1.822,5.76 2.833,5.76h18.334C22.177,5.76 23,6.567 23,7.56v10.8c0,0.993 -0.822,1.8 -1.833,1.8zM2.833,6.66c-0.505,0 -0.916,0.404 -0.916,0.9v10.8c0,0.496 0.41,0.9 0.916,0.9h18.334c0.505,0 0.916,-0.404 0.916,-0.9L22.083,7.56c0,-0.496 -0.41,-0.9 -0.916,-0.9L2.833,6.66z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
      <path
          android:pathData="M12.5,16.32L4.216,11.363c-0.22,-0.131 -0.282,-0.4 -0.14,-0.603 0.141,-0.203 0.434,-0.26 0.653,-0.13L12.5,15.28l7.771,-4.65c0.22,-0.13 0.512,-0.073 0.653,0.13 0.142,0.202 0.08,0.472 -0.14,0.603L12.5,16.32z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
      <path
          android:pathData="M3.455,17.28c-0.147,0 -0.291,-0.075 -0.378,-0.214 -0.14,-0.22 -0.084,-0.518 0.126,-0.665l4.09,-2.88c0.21,-0.147 0.491,-0.088 0.63,0.133 0.14,0.22 0.084,0.518 -0.126,0.666l-4.09,2.88c-0.078,0.054 -0.165,0.08 -0.252,0.08zM20.545,17.28c-0.087,0 -0.174,-0.026 -0.252,-0.08l-4.09,-2.88c-0.21,-0.148 -0.266,-0.445 -0.126,-0.666 0.139,-0.22 0.42,-0.28 0.63,-0.133l4.09,2.88c0.21,0.147 0.266,0.445 0.126,0.665 -0.087,0.14 -0.231,0.214 -0.378,0.214z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
    </vector>
    
  • id.xml Layout file:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
      <path
          android:pathData="M21.508,20L1.492,20C1.22,20 1,19.78 1,19.508L1,5.492C1,5.22 1.22,5 1.492,5h20.016c0.272,0 0.492,0.22 0.492,0.492v1.009h-0.937L21.063,5.938L1.937,5.938v13.126h19.126L21.063,8.001L22,8.001v11.507c0,0.272 -0.22,0.492 -0.492,0.492z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
      <path
          android:pathData="M7.5,13C6.12,13 5,11.88 5,10.501 5,9.123 6.12,8 7.5,8S10,9.12 10,10.499C10,11.877 8.88,13 7.5,13zM7.5,8.947c-0.855,0 -1.552,0.697 -1.552,1.552 0,0.855 0.697,1.551 1.552,1.551 0.855,0 1.552,-0.696 1.552,-1.551S8.355,8.947 7.5,8.947z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
      <path
          android:pathData="M10.848,17L4.476,17C4.213,17 4,16.785 4,16.521c0,-1.092 0.314,-2.188 0.864,-3.01 0.647,-0.964 1.577,-1.494 2.622,-1.494 0.258,0 0.468,0.212 0.468,0.471 0,0.26 -0.21,0.472 -0.468,0.472 -0.925,0 -1.513,0.587 -1.844,1.08 -0.37,0.554 -0.611,1.269 -0.682,2.017h5.403c-0.106,-1.05 -0.556,-2.031 -1.207,-2.585 -0.197,-0.168 -0.222,-0.465 -0.056,-0.665 0.166,-0.199 0.461,-0.224 0.66,-0.057 0.966,0.818 1.563,2.264 1.563,3.771 0,0.264 -0.213,0.479 -0.475,0.479zM13.003,9L19,9v0.943h-5.997L13.003,9zM13.003,12.005L19,12.005v0.943h-5.997v-0.943zM13.003,15.047h4.123v0.944h-4.123v-0.944z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
    </vector>
    
  • name.xml Layout file:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
      <path
          android:pathData="M20.289,16.908c-0.452,-1.078 -1.103,-2.047 -1.928,-2.878 -0.826,-0.831 -1.789,-1.485 -2.86,-1.94 -0.308,-0.132 -0.623,-0.245 -0.943,-0.34 1.3,-0.847 2.165,-2.321 2.165,-3.995C16.723,5.133 14.603,3 11.998,3 9.392,3 7.273,5.133 7.273,7.755c0,1.674 0.864,3.148 2.164,3.995 -0.32,0.095 -0.634,0.208 -0.943,0.34 -1.07,0.455 -2.034,1.109 -2.86,1.94 -0.825,0.831 -1.475,1.8 -1.928,2.878C3.236,18.025 3,19.211 3,20.434c0,0.312 0.252,0.566 0.562,0.566 0.311,0 0.563,-0.254 0.563,-0.566 0,-2.117 0.819,-4.108 2.306,-5.605C7.918,13.333 9.896,12.51 12,12.51s4.081,0.824 5.569,2.32c1.487,1.497 2.306,3.488 2.306,5.605 0,0.312 0.252,0.566 0.563,0.566 0.31,0 0.562,-0.254 0.562,-0.566 -0.005,-1.223 -0.243,-2.41 -0.711,-3.526zM8.395,7.753c0,-1.997 1.616,-3.623 3.6,-3.623 1.985,0 3.6,1.626 3.6,3.623 0,1.997 -1.615,3.623 -3.6,3.623 -1.984,0 -3.6,-1.626 -3.6,-3.623z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
    </vector>
    
  • password.xml Layout file:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
      <path
          android:pathData="M20.311,10.334c-0.441,-0.443 -1.036,-0.691 -1.659,-0.691h-1.174L17.478,6.5C17.478,3.46 15.024,1 12,1 8.976,1 6.522,3.46 6.522,6.5v3.143L5.348,9.643c-0.623,0 -1.221,0.248 -1.66,0.691C3.249,10.777 3,11.374 3,12v1.964C3,18.955 7.029,23 12,23c2.385,0 4.677,-0.952 6.364,-2.646C20.051,18.66 21,16.362 21,13.964L21,12c0,-0.625 -0.247,-1.226 -0.689,-1.666zM8.087,6.5C8.087,4.331 9.84,2.571 12,2.571s3.913,1.76 3.913,3.929v3.143L8.087,9.643L8.087,6.5zM19.435,13.964c0,4.124 -3.328,7.465 -7.435,7.465 -4.107,0 -7.435,-3.341 -7.435,-7.465L4.565,12c0,-0.434 0.35,-0.786 0.783,-0.786h13.304c0.432,0 0.783,0.352 0.783,0.786v1.964z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
      <path
          android:pathData="M12,12c-0.552,0 -1,0.373 -1,0.833v3.334c0,0.46 0.448,0.833 1,0.833s1,-0.373 1,-0.833v-3.334c0,-0.46 -0.448,-0.833 -1,-0.833z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
    </vector>
    
  • phone.xml Layout file:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
      <path
          android:pathData="M12.5,18.645c-0.64,0 -1.162,0.503 -1.162,1.121s0.522,1.121 1.162,1.121c0.64,0 1.162,-0.503 1.162,-1.12 0,-0.619 -0.522,-1.122 -1.162,-1.122zM18.247,1L6.753,1C5.787,1 5,1.76 5,2.692v18.616C5,22.24 5.787,23 6.753,23h11.494c0.966,0 1.753,-0.76 1.753,-1.692L20,2.692C20,1.76 19.213,1 18.247,1zM6.753,2.128h11.494c0.322,0 0.584,0.253 0.584,0.564L18.831,16.64L6.17,16.64L6.17,2.692c0,-0.31 0.262,-0.564 0.584,-0.564zM18.247,21.872L6.753,21.872c-0.322,0 -0.584,-0.253 -0.584,-0.564v-3.444h12.662v3.444c0,0.31 -0.262,0.564 -0.584,0.564z"
          android:fillColor="#D8D8D8"
          android:fillType="nonZero"/>
    </vector>
    
  • activity_main.xml Layout file:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline_right2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_end="40dp" />
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="40dp" />
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline_right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_end="40dp" />
    
        <ImageView
            android:id="@+id/img_bgName"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editText_name"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editText_name"
            app:layout_constraintVertical_bias="1.0"
            app:layout_constraintVertical_chainStyle="packed" />
    
        <ImageView
            android:id="@+id/img_bgID"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editTextID"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editTextID"
            app:layout_constraintVertical_chainStyle="packed" />
    
        <ImageView
            android:id="@+id/img_bgPass"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editTextID"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editTextID"
            app:layout_constraintVertical_bias="1.0" />
    
    
        <ImageView
            android:id="@+id/img_bgPass7"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editTextBirthday"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right2"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editTextBirthday" />
    
        <ImageView
            android:id="@+id/img_bgPass8"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editTextCellphone"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right2"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editTextCellphone" />
    
        <ImageView
            android:id="@+id/img_bgPass9"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editTextEmail"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right2"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editTextEmail" />
    
        <ImageView
            android:id="@+id/img_bgPass10"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editTextPassword"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right2"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editTextPassword" />
    
        <ImageView
            android:id="@+id/img_bgPass11"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/editTextPasswordAgain"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right2"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/editTextPasswordAgain" />
    
        <EditText
            android:id="@+id/editText_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp"
            android:layout_marginBottom="8dp"
            android:backgroundTint="#00FFFFFF"
            android:ems="18"
            android:inputType="textPersonName"
            android:text="@string/register_name"
            android:textSize="12sp"
            app:layout_constraintBottom_toTopOf="@+id/editTextID"
            app:layout_constraintStart_toEndOf="@+id/imageView12"
            app:layout_constraintTop_toBottomOf="@+id/textView2"
            app:layout_constraintVertical_chainStyle="packed" />
    
        <EditText
            android:id="@+id/editTextID"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp"
            android:layout_marginBottom="8dp"
            android:backgroundTint="#00FFFFFF"
            android:ems="18"
            android:inputType="textPersonName"
            android:text="@string/register_id"
            android:textSize="12sp"
            app:layout_constraintBottom_toTopOf="@+id/editTextBirthday"
            app:layout_constraintStart_toEndOf="@+id/imageView22"
            app:layout_constraintTop_toBottomOf="@+id/editText_name" />
    
        <EditText
            android:id="@+id/editTextBirthday"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp"
            android:layout_marginBottom="8dp"
            android:backgroundTint="#00FFFFFF"
            android:ems="18"
            android:inputType="textPersonName"
            android:text="@string/register_birthday"
            android:textSize="12sp"
            app:layout_constraintBottom_toTopOf="@+id/editTextCellphone"
            app:layout_constraintStart_toEndOf="@+id/imageView17"
            app:layout_constraintTop_toBottomOf="@+id/editTextID" />
    
        <EditText
            android:id="@+id/editTextCellphone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp"
            android:layout_marginBottom="8dp"
            android:backgroundTint="#00FFFFFF"
            android:ems="18"
            android:inputType="textPersonName"
            android:text="@string/register_cellPhone"
            android:textSize="12sp"
            app:layout_constraintBottom_toTopOf="@+id/editTextEmail"
            app:layout_constraintStart_toEndOf="@+id/imageView19"
            app:layout_constraintTop_toBottomOf="@+id/editTextBirthday" />
    
        <EditText
            android:id="@+id/editTextEmail"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp"
            android:layout_marginBottom="8dp"
            android:backgroundTint="#00FFFFFF"
            android:ems="18"
            android:inputType="textPersonName"
            android:text="@string/register_email"
            android:textSize="12sp"
            app:layout_constraintBottom_toTopOf="@+id/editTextPassword"
            app:layout_constraintStart_toEndOf="@+id/imageView21"
            app:layout_constraintTop_toBottomOf="@+id/editTextCellphone" />
    
        <EditText
            android:id="@+id/editTextPassword"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp"
            android:layout_marginBottom="8dp"
            android:backgroundTint="#00FFFFFF"
            android:ems="18"
            android:inputType="textPersonName"
            android:text="@string/register_password"
            android:textSize="12sp"
            app:layout_constraintBottom_toTopOf="@+id/editTextPasswordAgain"
            app:layout_constraintStart_toEndOf="@+id/imageView20"
            app:layout_constraintTop_toBottomOf="@+id/editTextEmail" />
    
        <EditText
            android:id="@+id/editTextPasswordAgain"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="6dp"
            android:layout_marginBottom="12dp"
            android:backgroundTint="#00FFFFFF"
            android:ems="18"
            android:inputType="textPersonName"
            android:text="@string/register_PasswordAgain"
            android:textSize="12sp"
            app:layout_constraintBottom_toTopOf="@+id/btn_apply"
            app:layout_constraintStart_toEndOf="@+id/imageView18"
            app:layout_constraintTop_toBottomOf="@+id/editTextPassword" />
    
        <Button
            android:id="@+id/btn_apply"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Apply"
            android:textColor="#FFFFFF"
            android:textSize="18sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/guideline_right"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toBottomOf="@+id/editTextPasswordAgain" />
    
        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="64dp"
            android:layout_marginBottom="16dp"
            android:text="@string/registration_form_title"
            android:textColor="#bf1f2a"
            android:textSize="24sp"
            app:layout_constraintBottom_toTopOf=""
            app:layout_constraintEnd_toStartOf="@+id/guideline_right"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.4"
            app:layout_constraintVertical_chainStyle="packed" />
    
        <ImageView
            android:id="@+id/imageView12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/img_bgName"
            app:layout_constraintStart_toStartOf="@+id/img_bgName"
            app:layout_constraintTop_toTopOf="@+id/img_bgName"
            app:srcCompat="@drawable/name" />
    
        <ImageView
            android:id="@+id/imageView22"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/img_bgID"
            app:layout_constraintStart_toStartOf="@+id/img_bgID"
            app:layout_constraintTop_toTopOf="@+id/img_bgID"
            app:srcCompat="@drawable/id" />
    
        <ImageView
            android:id="@+id/imageView17"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/img_bgPass7"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="@+id/img_bgPass7"
            app:srcCompat="@drawable/birthday" />
    
        <ImageView
            android:id="@+id/imageView18"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/img_bgPass11"
            app:layout_constraintStart_toStartOf="@+id/img_bgPass11"
            app:layout_constraintTop_toTopOf="@+id/img_bgPass11"
            app:srcCompat="@drawable/password" />
    
        <ImageView
            android:id="@+id/imageView21"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/img_bgPass9"
            app:layout_constraintStart_toStartOf="@+id/img_bgPass9"
            app:layout_constraintTop_toTopOf="@+id/img_bgPass9"
            app:srcCompat="@drawable/email" />
    
        <ImageView
            android:id="@+id/imageView20"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/img_bgPass10"
            app:layout_constraintStart_toStartOf="@+id/img_bgPass10"
            app:layout_constraintTop_toTopOf="@+id/img_bgPass10"
            app:srcCompat="@drawable/password" />
    
        <ImageView
            android:id="@+id/imageView19"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="@+id/img_bgPass8"
            app:layout_constraintStart_toStartOf="@+id/img_bgPass8"
            app:layout_constraintTop_toTopOf="@+id/img_bgPass8"
            app:srcCompat="@drawable/phone" />
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="15dp" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  • User class implementation:

    package com.example.userregistrationapp;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeParseException;
    import java.util.Locale;
    
    
    public class User  implements java.io.Serializable{
        private String fullName;
        private String personalID;
        private String dateOfBirth;
        private String cellPhoneNumber;
        private String emailInfo;
        private String password;
        private final String dateFormat = "yyyy-MM-dd";
    
        public User(String fullNameInput,
                    String personalIDInput,
                    String dateOfBirthInput,
                    String cellPhoneNumberInput,
                    String emailInfoInput,
                    String passwordInput) throws NoSuchAlgorithmException, NullPointerException, IllegalArgumentException
        //  User object constructor
        {
            //  Reference: https://stackoverflow.com/a/6358/6667035
            if (fullNameInput == null) {
                throw new NullPointerException("fullNameInput must not be null");
            }
            this.fullName = fullNameInput;
    
            if (personalIDInput == null) {
                throw new NullPointerException("personalIDInput must not be null");
            }
            this.personalID = personalIDInput;
    
            if (dateOfBirthInput == null) {
                throw new NullPointerException("dateOfBirthInput must not be null");
            }
            this.dateOfBirth = dateOfBirthInput;
    
            if (cellPhoneNumberInput == null) {
                throw new NullPointerException("cellPhoneNumberInput must not be null");
            }
            this.cellPhoneNumber = cellPhoneNumberInput;
    
            if (emailInfoInput == null) {
                throw new NullPointerException("emailInfoInput must not be null");
            }
            this.emailInfo = emailInfoInput;
    
            if (passwordInput == null) {
                throw new NullPointerException("passwordInput must not be null");
            }
            this.password = hashingMethod(passwordInput);
        }
    
        public String getFullName()
        {
            return this.fullName;
        }
    
        public String getPersonalID()
        {
            return this.personalID;
        }
    
        public String getDateOfBirth()
        {
            return this.dateOfBirth;
        }
    
        public String getCellPhoneNumber()
        {
            return this.cellPhoneNumber;
        }
    
        public String getEmailInfo()
        {
            return this.emailInfo;
        }
    
        public String getHash() throws NoSuchAlgorithmException
        {
            return hashingMethod(this.fullName + this.personalID);
        }
    
        public String getHashedPassword() throws NoSuchAlgorithmException
        {
            return this.password;
        }
    
        public boolean checkPassword(String password) {
            boolean result = false;
            try {
                result = this.password.equals(hashingMethod(password));
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return result;
        }
    
        //**********************************************************************************************
    
        //  Reference: https://stackoverflow.com/a/2624385/6667035
        private String hashingMethod(String inputString) throws NoSuchAlgorithmException {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            String stringToHash = inputString;
            messageDigest.update(stringToHash.getBytes());
            String stringHash = new String(messageDigest.digest());
            return stringHash;
        }
    }
    
  • strings.xml:

    <resources>
        <string name="app_name">UserRegistrationAPP</string>
        <string name="registration_form_title">Registration Form</string>
        <string name="register_name">Name</string>
        <string name="register_id">ID</string>
        <string name="register_birthday">birthday</string>
        <string name="register_cellPhone">CellPhone</string>
        <string name="register_email">Email</string>
        <string name="register_password">Password</string>
        <string name="register_PasswordAgain">Type Password Again</string>
        <string name="register_name_null_message">Please fill in name!</string>
        <string name="please_fill_in_register_id">Please fill in ID!</string>
        <string name="please_select_birthday">Please select birthday!</string>
        <string name="please_fill_in_register_cellPhone">Please fill in cellphone number!</string>
        <string name="please_fill_in_register_cellPhone_number">Please fill in correct cellphone number!</string>
        <string name="please_fill_in_Email">Please fill in Email!</string>
        <string name="please_fill_in_correct_Email">Please fill in correct Email!</string>
        <string name="please_fill_in_password">Please fill in password!</string>
        <string name="please_fill_in_confirm_password">Please fill in password again!</string>
        <string name="confirmation_password_not_equal">Please check passwords are equal!</string>
        <string name="send">Registration information have been sent!</string>
        <string name="OK">OK</string>
    </resources>
    
  • MainActivity.java implementation:

    package com.example.userregistrationapp;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.text.InputType;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import java.security.NoSuchAlgorithmException;
    import java.util.Calendar;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final EditText nameEditText = findViewById(R.id.editText_name);
            clickAndClear(nameEditText);
    
            final EditText personalIDEditText = findViewById(R.id.editTextID);
            clickAndClear(personalIDEditText);
    
            final EditText dateOfBirthInfoEditText = findViewById(R.id.editTextBirthday);
            View.OnClickListener dateOfBirthInfoClickHandler = v -> {
                if (v ==dateOfBirthInfoEditText) {
                    Calendar calendar = Calendar.getInstance();
                    int year = calendar.get(Calendar.YEAR);
                    int month = calendar.get(Calendar.MONTH);
                    int day = calendar.get(Calendar.DAY_OF_MONTH);
                    new android.app.DatePickerDialog(v.getContext(), (view, year1, month1, day1) -> {
                        String dateTime = String.valueOf(year1)+"-"+String.valueOf(month1)+"-"+String.valueOf(day1);
                        dateOfBirthInfoEditText.setText(dateTime);
                    }, year, month, day).show();
                }
            };
            dateOfBirthInfoEditText.setOnClickListener(dateOfBirthInfoClickHandler);
    
            final  EditText cellphoneNumberEditText = findViewById(R.id.editTextCellphone);
            clickAndClear(cellphoneNumberEditText);
    
            final EditText emailInfoEditText = findViewById(R.id.editTextEmail);
            clickAndClear(emailInfoEditText);
    
            final EditText passwordEditText = findViewById(R.id.editTextPassword);
            clickAndClear(passwordEditText, true);
    
            final EditText confirmPasswordEditText = findViewById(R.id.editTextPasswordAgain);
            clickAndClear(confirmPasswordEditText, true);
    
            final Button applyButton = findViewById(R.id.btn_apply);
            View.OnClickListener ApplyButtonClickHandler = v -> {
                if (v == applyButton) {
                    //  Parsing Information
                    String nameString = getEditTextContent(nameEditText);
                    String personalIDString = getEditTextContent(personalIDEditText);
                    String dateOfBirtString = getEditTextContent(dateOfBirthInfoEditText);
                    String cellphoneNumberString = getEditTextContent(cellphoneNumberEditText);
                    String emailInfoString = getEditTextContent(emailInfoEditText);
                    String passwordString = getEditTextContent(passwordEditText);
                    String confirmPasswordString = getEditTextContent(confirmPasswordEditText);
    
                    //  Checking Information
                    if ((nameString.isEmpty()) || (nameString.contains(getResources().getString(R.string.register_name)))) {
                        showAlertDialog(getResources().getString(R.string.register_name_null_message), getResources().getString(R.string.OK));
                        return;
                    }
                    if ((personalIDString.isEmpty()) || (personalIDString.equals(getResources().getString(R.string.register_id)))) {
                        showAlertDialog(getResources().getString(R.string.please_fill_in_register_id), getResources().getString(R.string.OK));
                        return;
                    }
                    if ((dateOfBirtString.isEmpty()) || (dateOfBirtString.equals(getResources().getString(R.string.register_birthday)))) {
                        showAlertDialog(getResources().getString(R.string.please_select_birthday), getResources().getString(R.string.OK));
                        return;
                    }
                    if ((cellphoneNumberString.isEmpty()) || (cellphoneNumberString.equals(getResources().getString(R.string.register_cellPhone)))) {
                        showAlertDialog(getResources().getString(R.string.please_fill_in_register_cellPhone), getResources().getString(R.string.OK));
                        return;
                    }
                    if (checkCellphoneNumber(cellphoneNumberEditText.getText().toString()) == false) {
                        showAlertDialog(getResources().getString(R.string.please_fill_in_register_cellPhone_number), getResources().getString(R.string.OK));
                        return;
                    }
                    if ((emailInfoString.isEmpty()) || (emailInfoString.equals(getResources().getString(R.string.register_email)))) {
                        showAlertDialog(getResources().getString(R.string.please_fill_in_Email), getResources().getString(R.string.OK));
                        return;
                    }
                    if (checkEmail(emailInfoString)==false) {
                        showAlertDialog(getResources().getString(R.string.please_fill_in_correct_Email), getResources().getString(R.string.OK));
                        return;
                    }
                    if (passwordString.isEmpty() || passwordString.equals(getResources().getString(R.string.register_password))) {
                        showAlertDialog(getResources().getString(R.string.please_fill_in_password), getResources().getString(R.string.OK));
                        return;
                    }
                    if (confirmPasswordString.isEmpty()) {
                        showAlertDialog(getResources().getString(R.string.please_fill_in_confirm_password), getResources().getString(R.string.OK));
                        return;
                    }
                    if (passwordString.equals(confirmPasswordString) == false) {
                        showAlertDialog(getResources().getString(R.string.confirmation_password_not_equal), getResources().getString(R.string.OK));
                        return;
                    }
                    try {
                        sendRegisterInfo(new User(
                                nameString,
                                personalIDString,
                                dateOfBirtString,
                                cellphoneNumberString,
                                emailInfoString,
                                passwordString
                        ));
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    }
                    showToast(getResources().getString(R.string.send), Toast.LENGTH_SHORT);
                }
            };
            applyButton.setOnClickListener(ApplyButtonClickHandler);
    
            return;
        }
    
        private void sendRegisterInfo(User newUser) {
            //  TODO: perform send operation!
            return;
        }
    
        private boolean checkEmail(String input) {
            return input.contains("@");
        }
    
        private boolean checkCellphoneNumber(String input) {
            return isNumeric(input);
        }
    
        private boolean isNumeric(String s) {
            return s != null && s.matches("[-+]?\\d*\\.?\\d+");
        }
    
        private String getEditTextContent(final EditText editTextInput) {
            return editTextInput.getText().toString();
        }
    
        private void showToast(String textInput, int duration) {
            Context context = getApplicationContext();
            CharSequence text = textInput;
            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }
    
        private void showAlertDialog(String titleString, String stringOnPositiveButton) {
            androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(this);
            builder.setMessage(titleString)
                    .setPositiveButton(stringOnPositiveButton, (dialog, id) -> {
    
                    });
            builder.show();
        }
    
        //  clickAndClear method
        //  Clear EditText content after clicking it.
        private void clickAndClear(final EditText editTextInput) {
            View.OnClickListener editTextViewClickHandler = v -> {
                if (v == editTextInput) {
                    editTextInput.setText("");
                }
            };
            editTextInput.setOnClickListener(editTextViewClickHandler);
        }
    
        //  clickAndClear method
        //  Clear EditText content after clicking it.
        //  If isPassword==true, hide characters like `***` with `.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);` syntax.
        private void clickAndClear(final EditText editTextInput, final boolean isPassword) {
            View.OnClickListener editTextViewClickHandler = v -> {
                if (v == editTextInput) {
                    editTextInput.setText("");
                    if (isPassword ==true) {
                        editTextInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
                    }
                }
            };
            editTextInput.setOnClickListener(editTextViewClickHandler);
        }
    }
    

All suggestions are welcome.

The summary information:

  • Which question it is a follow-up to?

    Android APP User class implementation

  • What changes has been made in the code since last question?

    Besides creating User class, the full registration page implementation is shown in this post.

  • Why a new review is being asked for?

    If there is any possible improvement, please let me know.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

throws

Unchecked exceptions aren't usually declared as being thrown by functions. So you don't really need to say that the constructor can throw NullPointerException. I don't really like that you're throwing NullPointerException, it seems unusual to me, however as the linked question and it's many related questions say, this is an area of debate/personal taste. Your User constructor says it throws IllegalArgumentException, but I can't see an obvious place that this actually happens. Some IDEs will highlight these types of issues for you so that you don't forget to remove throws declarations if you remove the code that actually throws the exception...

Your getHashedPassword definitely doesn't throw NoSuchAlgorithmException for example since it only returns a member variable.

this

You don't need to use this. ever time you reference a member variable. In most instances it just adds noise/overhead that doesn't need to be there. Generally speaking, the only time that I'd expect to see this. is if you're passing in parameters that have the same name as the member variable and you need to disambiguate the references (usually in a constructor or a set method).

catch

You rarely want to catch Exception. This is generally reserved for top level, catch all cases (such as around an API endpoint to allow the exception to be translated into a response code). If your code can actually handle an exception, then you should be catching the specific exceptions that you are interested in, that way you don't accidently ignore an exception you weren't really expecting. So, checkPassword should probably be catching NoSuchAlgorithmException.

Say what you mean...

It seems likely to me that sendRegisterInfo will have the possibility for failure. You've also coded your User constructor with the expectation that hashing the password might not work. This results in a try/catch block in your MainActivity. However, all the catch does is print the stack and swallow the exception. As far as the user is concerned, they get a toast telling them the registration information has been sent. It's generally bad customer relations to mislead your users...

Apply

Apply is a funny name for a button that sends registration information. Maybe it makes sense in the rest of the screen flow (which I haven't looked at), however I'd expect something more like submit or register.

You're also directly setting the android:text to "Apply" in the button declaration. Generally you'd want to use a string resource instead, indeed buttons are one of the first things I'd expect you to want to internationalise if you wanted to support multiple languages in the future.

clickAndClear

I might have missed something, however this method looks like it would drive me a bit crazy as a user. It makes sense for you to clear the text box when I first click on it, if it has some default value in it. However to me, it looks like if I fill out your registration information, then realise I've missed a letter in my e-mail address and click to update it, that you'll throw away what I've previously typed and rather than just adding in the missing character I'll have to type the whole address in again from scratch. I'd find that rather frustrating.

Password

You're setting the inputType for your password fields programmatically. Is there a reason that you're not setting it directly in the layout file?

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.