Building a Feature-Rich Calculator Application Using Android Studio

System Architecture

This implementation demonstrates the construction of a modular calculator application leveraging Android Studio and the Java programming language. The architecture integrates several foundational Android components, including a timed initialization sequence, persistent credential management via SQLite, fragment-driven view swapping, and session-aware profile controls.

Component Breakdown

  • Launch Interface: Renders a branded graphic and executes an automated countdown before routing to authentication.
  • Authentication Layer: Manages account provisioning and credential verification through local relational storage.
  • Navigation Hub: Utilizes FrameLayout to dynamically host interchangeable fragments for calculation and user management.
  • Account View: Displays active session identifiers and handles credential clearance.

Environment & Configuration

Development requires Android Studio targeting minimum SDK 24 (Android 7.0) to ensure compatibility across 95%+ of active Android devices. Project directories should reside on a secondary drive using standard ASCII naming conventions to prevent build path errors. Initialize an Empty Project template to establish the baseline Gradle configuration.

UI Construction & Implementation Strategy

Adopt a resource-first workflow: define XML layouts completely before wiring behavioral logic in Java classes. This separation streamlines debugging and enables parallel UI iteration.

Initialization Screen Layout

The splash view centers visual assets and employs a background handler for timing logic.

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2D3250">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/launchGraphic"
            android:layout_width="140dp"
            android:layout_height="140dp"
            android:contentDescription="Application Logo"
            android:src="@drawable/ic_app_icon" />

        <TextView
            android:id="@+id/appTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:text="Calculator Pro"
            android:textColor="#A8B5D6"
            android:textSize="26sp"
            android:textStyle="bold" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Account Creation Interface

The registration view validates input consistency before committing to the database.

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp">

    <TextView
        android:id="@+id/registrationHeader"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Account"
        android:textColor="#A8B5D6"
        android:textSize="30sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/fieldAccount"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:hint="Username"
        android:inputType="textPersonName"
        android:padding="12dp"
        android:textColorHint="#8A9BBF"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/registrationHeader" />

    <EditText
        android:id="@+id/fieldSecret"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:hint="Password"
        android:inputType="textPassword"
        android:padding="12dp"
        android:textColorHint="#8A9BBF"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/fieldAccount" />

    <EditText
        android:id="@+id/fieldVerify"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:hint="Confirm Password"
        android:inputType="textPassword"
        android:padding="12dp"
        android:textColorHint="#8A9BBF"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/fieldSecret" />

    <Button
        android:id="@+id/submitBtn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:background="#6B7FA3"
        android:text="Create Profile"
        android:textColor="#FFFFFF"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/fieldVerify" />

    <TextView
        android:id="@+id/navigateBack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:clickable="true"
        android:text="Returning user? Sign in"
        android:textColor="#6B7FA3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/submitBtn" />
</androidx.constraintlayout.widget.ConstraintLayout>

Registration Activity Logic

The activity binds view references, performs string validation, and delegates persistence to a custom SQLite helper.

package com.app.calculator.authentication;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.app.calculator.R;
import com.app.calculator.database.ProfileRepository;

public class SignupActivity extends AppCompatActivity {

    private EditText accountInput;
    private EditText passwordInput;
    private EditText verifyInput;
    private ProfileRepository localDb;

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_signup);

        localDb = new ProfileRepository(this);
        accountInput = findViewById(R.id.fieldAccount);
        passwordInput = findViewById(R.id.fieldSecret);
        verifyInput = findViewById(R.id.fieldVerify);
        Button creationBtn = findViewById(R.id.submitBtn);
        TextView returnLink = findViewById(R.id.navigateBack);

        creationBtn.setOnClickListener(v -> executeSignup());
        returnLink.setOnClickListener(v -> finish());
    }

    private void executeSignup() {
        String user = accountInput.getText().toString().trim();
        String pass = passwordInput.getText().toString().trim();
        String check = verifyInput.getText().toString().trim();

        if (user.isEmpty() || pass.isEmpty()) {
            notifyUser("All fields are required");
            return;
        }
        if (!pass.equals(check)) {
            notifyUser("Password mismatch detected");
            return;
        }

        boolean success = localDb.insertProfile(user, pass);
        if (success) {
            notifyUser("Account registered successfully");
            finish();
        } else {
            notifyUser("Database insertion failed");
        }
    }

    private void notifyUser(String message) {
        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
    }
}

Login Controller

The authentication screen verifies submitted credentials against stored records and initiates session tracking.

package com.app.calculator.authentication;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.app.calculator.R;
import com.app.calculator.database.ProfileRepository;
import com.app.calculator.dashboard.MainContainer;

public class LoginActivity extends AppCompatActivity {

    private EditText credentialInput;
    private EditText pinInput;
    private ProfileRepository dbHandler;
    private SharedPreferences sessionManager;

    @Override
    protected void onCreate(Bundle state) {
        super.onCreate(state);
        setContentView(R.layout.activity_login);

        dbHandler = new ProfileRepository(this);
        sessionManager = getSharedPreferences("AppSession", MODE_PRIVATE);

        credentialInput = findViewById(R.id.loginUser);
        pinInput = findViewById(R.id.loginPass);
        Button accessBtn = findViewById(R.id.loginBtn);
        TextView signupRedirect = findViewById(R.id.createAccountLink);

        signupRedirect.setOnClickListener(v -> startActivity(new Intent(this, SignupActivity.class)));

        accessBtn.setOnClickListener(v -> verifyIdentity());
    }

    private void verifyIdentity() {
        String id = credentialInput.getText().toString().trim();
        String secret = pinInput.getText().toString().trim();

        if (dbHandler.authenticateUser(id, secret)) {
            sessionManager.edit().putString("current_identity", id).apply();
            startActivity(new Intent(this, MainContainer.class));
            finish();
        } else {
            Toast.makeText(getApplicationContext(), "Invalid credentials", Toast.LENGTH_SHORT).show();
        }
    }
}

Fragment Navigation Container

The primary activity utilizes a lightweight frame to swap between operational modules based on bottom bar selections.

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#1C2038">

    <FrameLayout
        android:id="@+id/viewSwitcher"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/navStrip"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:id="@+id/navStrip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#252A45"
        android:orientation="horizontal"
        android:padding="10dp"
        app:layout_constraintBottom_toBottomOf="parent">

        <TextView
            android:id="@+id/tabCompute"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="Calculator"
            android:textColor="#D0D8F0" />

        <TextView
            android:id="@+id/tabProfile"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="Account"
            android:textColor="#7A85A3" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Profile Fragment & Session Handling

The account view reads persistent state, updates visual indicators, and provides a secure logout routine.

package com.app.calculator.dashboard;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.app.calculator.R;

public class AccountView extends Fragment {

    private TextView identityLabel;
    private TextView actionLogout;
    private SharedPreferences preferences;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle saved) {
        return inflater.inflate(R.layout.fragment_account, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View root, @Nullable Bundle state) {
        super.onViewCreated(root, state);
        preferences = requireActivity().getSharedPreferences("AppSession", requireActivity().MODE_PRIVATE);

        identityLabel = root.findViewById(R.id.userDisplay);
        actionLogout = root.findViewById(R.id.signOutBtn);

        refreshSessionState();
        actionLogout.setOnClickListener(v -> handleSignOut());
    }

    private void refreshSessionState() {
        String activeUser = preferences.getString("current_identity", "");
        if (!activeUser.isEmpty()) {
            identityLabel.setText("Signed in as " + activeUser);
            actionLogout.setEnabled(true);
            actionLogout.setTextColor(0xFFD0D8F0);
        } else {
            identityLabel.setText("No active session");
            actionLogout.setEnabled(false);
            actionLogout.setTextColor(0xFF556080);
        }
    }

    private void handleSignOut() {
        preferences.edit().remove("current_identity").commit();
        refreshSessionState();
        Toast.makeText(requireContext(), "Session terminated", Toast.LENGTH_SHORT).show();
    }
}

Deployment & Verification

Compile the module using Gradle and deploy to an emulator or physical device running API 24 or newer. Validate SQLite operations by inspecting the generated database file at /data/data/[package_name]/databases/ using the Android Device Monitor. Ensure fragment transactions execute without state loss during orientation changes by configuring setRetainInstance(true) or handling configuration flags appropriately. Fragment switching should respond instantly to navigation inputs, and shared preference updates must persist across application lifecycle closures.

Tags: android-studio java-android sqlite-database fragment-navigation constraint-layout

Posted on Sun, 07 Jun 2026 16:49:41 +0000 by mraza