Search code examples
databasesqliteandroid-studioauthenticationandroid-sqlite

Registration App in Android Studio crashes without any view using SQLite database


I am working on Android Studio to create Login and Registration app using SQLite. I couldn't understand my error the app gets closed automatically. Hoping someone could help me with the unknown error.

Activity 1 (MainActivity): If username and password details are correct. It navigates to HandsOnActivity(Activity 4).

Activity 2 (Registration Activity) : User details are entered like (Username, Password, Confirm Password, Email, Password) and Register button. To verify the user and add into Sqlite database. Username,Password,Confirm Password gets input from TextInputEditText And email,phonenumber from EditText. Activity3 and Activity 4 are been added with a simple textbox and layouts with setContentView(). I want to check both email and username while logining in into the app.

Activity1 Page

MainActivity.java

package com.android.loginapp;
   import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    import androidx.appcompat.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity {
        private EditText EditTextUserName;
        private EditText EditTextUserPassword;
        private Button buttonLogin;
        private Button buttonReset;
        private Button buttonCreateUser;
        LoginDatabase MyDb;
        String username = EditTextUserName.getText().toString();
        String password = EditTextUserPassword.getText().toString();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.login_activity);
    
            EditTextUserName = findViewById(R.id.edittext_username);
            EditTextUserPassword =  findViewById(R.id.edittext_password);
            buttonLogin = findViewById(R.id.button_login);
            buttonReset = findViewById(R.id.button_reset);
            buttonCreateUser = findViewById(R.id.button_createaccount);
            MyDb = new LoginDatabase(this);
            //Reset function
            buttonReset.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    EditTextUserName.setText("");
                    EditTextUserPassword.setText("");
                }
            });
            //Create a new user function
            buttonCreateUser.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent registerIntent = new Intent(MainActivity.this,RegistrationActivity.class);
                    startActivity(registerIntent);
                }
            });
            //Login button Navigation and Verification Function
            buttonLogin.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(username.isEmpty() | password.isEmpty()){
                        EditTextUserName.setError("Field can't be empty");
                        EditTextUserPassword.setError("Field can't be empty");
                    } else{
                        boolean checkUsernamePassword = MyDb.checkUsernamePassword(username, password);
                        if(checkUsernamePassword){
                            Toast.makeText(MainActivity.this,"UsernamePassword Login Successful",Toast.LENGTH_SHORT).show();
                            Intent intent1 = new Intent(getApplicationContext(), HandsOnActivity.class);
                            startActivity(intent1);
                        } else{
                            Toast.makeText(MainActivity.this,"Invalid Credentials",Toast.LENGTH_SHORT).show();
                        }
                        boolean checkEmailPassword = MyDb.checkEmailPassword(username, password);
                        if(checkEmailPassword){
                            Toast.makeText(MainActivity.this,"EmailPassword Login Successful",Toast.LENGTH_SHORT).show();
                            Intent intent2 = new Intent(getApplicationContext(), HandsOnActivity.class);
                            startActivity(intent2);
                        }else {
                            Toast.makeText(MainActivity.this,"Invalid Credentials",Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });
    
        }
    }

RegistrationActivity. java file

package com.android.loginapp;
import android.content.Intent;
import android.os.Bundle;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputLayout;

public class RegistrationActivity extends AppCompatActivity {
    TextInputLayout textInputUserName;
    TextInputLayout textInputUserPassword;
    TextInputLayout textInputUserConfirmPassword;
    EditText userPhoneNumber;
    EditText userEmailAddress;
    Button buttonRegisterUser;
    String MobilePattern="[0-9]{10}";
    LoginDatabase MyDb;
    String usernameInput = textInputUserName.getEditText().getText().toString().trim();
    String passwordInput = textInputUserPassword.getEditText().getText().toString().trim();
    String confirmPasswordInput = textInputUserConfirmPassword.getEditText().getText().toString().trim();

    String phoneNumberInput = userPhoneNumber.getText().toString();
    String emailInput = userEmailAddress.getText().toString().trim();


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.registration_activity);
        textInputUserName = findViewById(R.id.text_input_username);
        textInputUserPassword = findViewById(R.id.text_input_password);
        textInputUserConfirmPassword = findViewById(R.id.text_input_confirmPassword);
        userPhoneNumber = (EditText) findViewById(R.id.editTextPhone);
        userEmailAddress = (EditText) findViewById(R.id.edittext_emailAddress);
        buttonRegisterUser = (Button) findViewById(R.id.button_registerUser);
        MyDb = new LoginDatabase(this);

        buttonRegisterUser.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!validateEmail() | !validateUsername() | !validatePassword() | !validatePhoneNumber()) {
                    return;
                }else if(passwordInput.equals(confirmPasswordInput)){
                    boolean checkUser = MyDb.checkUsername(usernameInput);
                    boolean checkEmail = MyDb.checkEmail(emailInput);
                    if(!checkUser & !checkEmail){
                        boolean insert = MyDb.insertData(usernameInput, passwordInput, phoneNumberInput, emailInput);
                        if (insert){
                            Toast.makeText(getApplicationContext(),"Registered Successfully",Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(RegistrationActivity.this,RegisteredActivity.class);
                            startActivity(intent);
                        }else {
                            Toast.makeText(RegistrationActivity.this, "Registration Failed", Toast.LENGTH_SHORT).show();
                        }
                    }else {
                        Toast.makeText(RegistrationActivity.this,"User already exists",Toast.LENGTH_SHORT).show();
                    }
                }else {
                    Toast.makeText(getApplicationContext(),"Password doesn't match",Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private boolean validateEmail () {
        if(emailInput.isEmpty()) {
            userEmailAddress.setError("Field can't be empty");
            return false;
        } else if (!Patterns.EMAIL_ADDRESS.matcher(emailInput).matches()){
            userEmailAddress.setError("Please enter a valid email address");
            return  false;
        } else {
            userEmailAddress.setError(null);
            return true;
        }
    }
     private boolean validateUsername() {
        if(usernameInput.isEmpty()) {
            textInputUserName.setError("Field can't be empty");
            return false;
        } else if(usernameInput.length()>15){
            textInputUserName.setError("Username too long");
            return false;
        } else {
            textInputUserName.setError(null);
            return true;
        }
    }
    private boolean validatePassword(){
        if(passwordInput.isEmpty() | confirmPasswordInput.isEmpty()){
            textInputUserPassword.setError("Field can't be empty");
            textInputUserConfirmPassword.setError("Field can't be empty");
            return false;
        } else {
            textInputUserPassword.setError(null);
            textInputUserConfirmPassword.setError(null);
            return true;
        }
    }
    private boolean validatePhoneNumber(){
        if(phoneNumberInput.isEmpty()){
            userPhoneNumber.setError("Field can't be empty");
            return false;
        } else if(phoneNumberInput.matches(MobilePattern)){
            return phoneNumberInput.length() > 6 && phoneNumberInput.length() <=10;
        }else{
            userPhoneNumber.setError("Number invalid");
            return false;
        }
    }
}

Database File

package com.android.loginapp;
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    
    
    public class LoginDatabase extends SQLiteOpenHelper {
        public static final String DBNAME = "Login.db";
    
        public LoginDatabase(Context context) {
            super(context, "Login.db", null, 1);
        }
    
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE users(username TEXT primary key, password TEXT, phoneNumber INTEGER, email VARCHAR(320))");
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE if exists users");
        }
    
        public boolean insertData(String username, String password, String phoneNumber, String email){
            SQLiteDatabase db = this.getWritableDatabase();
            ContentValues contentValues = new ContentValues();
            contentValues.put("username", username);
            contentValues.put("password", password);
            contentValues.put("phoneNumber", phoneNumber);
            contentValues.put("email", email);
            long result = db.insert("users", null,contentValues);
            if(result == -1) return  false;
            else return true;
        }
        public boolean checkUsername(String username){
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery("SELECT * FROM users WHERE username = ?", new String[] {username});
            if(cursor.getCount()>0) return true; // If user exists
            else return false;
        }
    
        public boolean checkUsernamePassword(String username, String password){
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery("SELECT * FROM users where username = ? and password = ?", new String[] {username,password});
            if(cursor.getCount()>0) return true;
            else return false;
        }
        public boolean checkEmail(String email){
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery("SELECT * FROM users WHERE email = ?",new String[] {email});
            if(cursor.getCount()>0) return true;
            else return false;
        }
        public boolean checkEmailPassword(String email, String password){
            SQLiteDatabase db = this.getWritableDatabase();
            Cursor cursor = db.rawQuery("SELECT * FROM users WHERE email = ? and password = ?",new String[] {email, password});
            if(cursor.getCount()>0) return true;
            else return false;
        }
    }
  

Manifest File

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.loginapp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".RegistrationActivity">

        </activity>
        <activity android:name=".RegisteredActivity">

        </activity>
        <activity android:name=".HandsOnActivity">

        </activity>

    </application>

</manifest>

Error found after debugging:

$ adb shell am start -n "com.android.loginapp/com.android.loginapp.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -D
Waiting for application to come online: com.android.loginapp | com.android.loginapp.test
Waiting for application to come online: com.android.loginapp | com.android.loginapp.test
Connected to process 1516 on device 'samsung-sm_m307f-RZ8M92DBXEE'.
Connecting to com.android.loginapp
Connected to the target VM, address: 'localhost:8602', transport: 'socket'
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/ndroid.loginap: Late-enabling -Xcheck:jni
E/ndroid.loginap: Unknown bits set in runtime_flags: 0x8000
D/ActivityThread: setConscryptValidator
    setConscryptValidator - put
W/ActivityThread: Application com.android.loginapp is waiting for the debugger on port 8100...
I/System.out: Sending WAIT chunk
I/System.out: Debugger has connected
I/System.out: waiting for debugger to settle...
I/chatty: uid=10111(com.android.loginapp) identical 3 lines
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: debugger has settled (1499)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.android.loginapp, PID: 1516
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.android.loginapp/com.android.loginapp.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3341)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7814)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
        at com.android.loginapp.MainActivity.<init>(MainActivity.java:17)
        at java.lang.Class.newInstance(Native Method)
        at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
        at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1251)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3329)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:7814) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1068) 
Disconnected from the target VM, address: 'localhost:8602', transport: 'socket'

Solution

  • You are doing the following things wrong

    String username = EditTextUserName.getText().toString();
    String password = EditTextUserPassword.getText().toString();
    

    The above two statements needs to be written after the following statements:

    buttonLogin.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if(username.isEmpty() | password.isEmpty()){
                            EditTextUserName.setError("Field can't be empty");
                            EditTextUserPassword.setError("Field can't be empty");
                        } else{
    

    Just copy the first 2 statements below these. The reason you were getting NullPointer was that you were accessing variables that were not even initialized.

    So your actual code would look like:-

    buttonLogin.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(username.isEmpty() | password.isEmpty()){
                        EditTextUserName.setError("Field can't be empty");
                        EditTextUserPassword.setError("Field can't be empty");
                    } else{
                        username = EditTextUserName.getText().toString();
                        password = EditTextUserPassword.getText().toString();
                        boolean checkUsernamePassword = MyDb.checkUsernamePassword(username, password);
                        if(checkUsernamePassword){
                            Toast.makeText(MainActivity.this,"UsernamePassword 
                           Login Successful",Toast.LENGTH_SHORT).show();
                            Intent intent1 = new Intent(getApplicationContext(), 
                            HandsOnActivity.class);
                            startActivity(intent1);
                          } else{
                            Toast.makeText(MainActivity.this,"Invalid 
                            Credentials",Toast.LENGTH_SHORT).show();
                        }