From c449a0c262b9dd7f68d620167e534caa5b75260c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 7 Feb 2026 06:51:39 +0000 Subject: [PATCH] Add COSC 341 Lab 2 code: Question 1 (Registration App) and Question 2 (Map/Web App) in Java and XML Co-authored-by: Kithe --- Question1/app/build.gradle | 34 ++++ Question1/app/src/main/AndroidManifest.xml | 26 +++ .../registrationapp/DisplayActivity.java | 35 ++++ .../example/registrationapp/MainActivity.java | 169 ++++++++++++++++++ .../app/src/main/res/drawable/app_logo.xml | 18 ++ .../app/src/main/res/drawable/ic_calendar.xml | 11 ++ .../app/src/main/res/drawable/ic_email.xml | 11 ++ .../app/src/main/res/drawable/ic_lock.xml | 11 ++ .../app/src/main/res/drawable/ic_person.xml | 11 ++ .../src/main/res/layout/activity_display.xml | 99 ++++++++++ .../app/src/main/res/layout/activity_main.xml | 121 +++++++++++++ Question1/app/src/main/res/values/colors.xml | 9 + Question1/app/src/main/res/values/strings.xml | 4 + Question1/build.gradle | 4 + Question1/gradle.properties | 2 + Question1/settings.gradle | 17 ++ Question2/app/build.gradle | 35 ++++ Question2/app/src/main/AndroidManifest.xml | 35 ++++ .../com/example/mapwebapp/MainActivity.java | 40 +++++ .../com/example/mapwebapp/MapsActivity.java | 49 +++++ .../example/mapwebapp/WebViewActivity.java | 41 +++++ .../app/src/main/res/layout/activity_main.xml | 33 ++++ .../app/src/main/res/layout/activity_maps.xml | 9 + .../src/main/res/layout/activity_webview.xml | 12 ++ Question2/app/src/main/res/values/colors.xml | 9 + Question2/app/src/main/res/values/strings.xml | 4 + Question2/build.gradle | 4 + Question2/gradle.properties | 2 + Question2/settings.gradle | 17 ++ 29 files changed, 872 insertions(+) create mode 100644 Question1/app/build.gradle create mode 100644 Question1/app/src/main/AndroidManifest.xml create mode 100644 Question1/app/src/main/java/com/example/registrationapp/DisplayActivity.java create mode 100644 Question1/app/src/main/java/com/example/registrationapp/MainActivity.java create mode 100644 Question1/app/src/main/res/drawable/app_logo.xml create mode 100644 Question1/app/src/main/res/drawable/ic_calendar.xml create mode 100644 Question1/app/src/main/res/drawable/ic_email.xml create mode 100644 Question1/app/src/main/res/drawable/ic_lock.xml create mode 100644 Question1/app/src/main/res/drawable/ic_person.xml create mode 100644 Question1/app/src/main/res/layout/activity_display.xml create mode 100644 Question1/app/src/main/res/layout/activity_main.xml create mode 100644 Question1/app/src/main/res/values/colors.xml create mode 100644 Question1/app/src/main/res/values/strings.xml create mode 100644 Question1/build.gradle create mode 100644 Question1/gradle.properties create mode 100644 Question1/settings.gradle create mode 100644 Question2/app/build.gradle create mode 100644 Question2/app/src/main/AndroidManifest.xml create mode 100644 Question2/app/src/main/java/com/example/mapwebapp/MainActivity.java create mode 100644 Question2/app/src/main/java/com/example/mapwebapp/MapsActivity.java create mode 100644 Question2/app/src/main/java/com/example/mapwebapp/WebViewActivity.java create mode 100644 Question2/app/src/main/res/layout/activity_main.xml create mode 100644 Question2/app/src/main/res/layout/activity_maps.xml create mode 100644 Question2/app/src/main/res/layout/activity_webview.xml create mode 100644 Question2/app/src/main/res/values/colors.xml create mode 100644 Question2/app/src/main/res/values/strings.xml create mode 100644 Question2/build.gradle create mode 100644 Question2/gradle.properties create mode 100644 Question2/settings.gradle diff --git a/Question1/app/build.gradle b/Question1/app/build.gradle new file mode 100644 index 0000000..0ab5a1e --- /dev/null +++ b/Question1/app/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'com.example.registrationapp' + compileSdk 36 + + defaultConfig { + applicationId "com.example.registrationapp" + minSdk 24 + targetSdk 36 + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.11.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' +} diff --git a/Question1/app/src/main/AndroidManifest.xml b/Question1/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..5655d06 --- /dev/null +++ b/Question1/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + diff --git a/Question1/app/src/main/java/com/example/registrationapp/DisplayActivity.java b/Question1/app/src/main/java/com/example/registrationapp/DisplayActivity.java new file mode 100644 index 0000000..337cd2b --- /dev/null +++ b/Question1/app/src/main/java/com/example/registrationapp/DisplayActivity.java @@ -0,0 +1,35 @@ +package com.example.registrationapp; + +import android.os.Bundle; +import android.widget.TextView; + +import androidx.appcompat.app.AppCompatActivity; + +public class DisplayActivity extends AppCompatActivity { + + private TextView textViewName, textViewEmail, textViewGender, textViewDOB; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_display); + + // Initialize views + textViewName = findViewById(R.id.textViewName); + textViewEmail = findViewById(R.id.textViewEmail); + textViewGender = findViewById(R.id.textViewGender); + textViewDOB = findViewById(R.id.textViewDOB); + + // Get data from intent + String name = getIntent().getStringExtra("name"); + String email = getIntent().getStringExtra("email"); + String gender = getIntent().getStringExtra("gender"); + String dob = getIntent().getStringExtra("dob"); + + // Display the information (password is NOT shown) + textViewName.setText(name); + textViewEmail.setText(email); + textViewGender.setText(gender); + textViewDOB.setText(dob); + } +} diff --git a/Question1/app/src/main/java/com/example/registrationapp/MainActivity.java b/Question1/app/src/main/java/com/example/registrationapp/MainActivity.java new file mode 100644 index 0000000..a0f6a4c --- /dev/null +++ b/Question1/app/src/main/java/com/example/registrationapp/MainActivity.java @@ -0,0 +1,169 @@ +package com.example.registrationapp; + +import android.app.DatePickerDialog; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import java.util.Calendar; +import java.util.regex.Pattern; + +public class MainActivity extends AppCompatActivity { + + private EditText editTextName, editTextEmail, editTextDOB, editTextPassword; + private RadioGroup radioGroupGender; + private Button buttonRegister; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Initialize views + editTextName = findViewById(R.id.editTextName); + editTextEmail = findViewById(R.id.editTextEmail); + editTextDOB = findViewById(R.id.editTextDOB); + editTextPassword = findViewById(R.id.editTextPassword); + radioGroupGender = findViewById(R.id.radioGroupGender); + buttonRegister = findViewById(R.id.buttonRegister); + + // DatePickerDialog for Date of Birth + editTextDOB.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showDatePickerDialog(); + } + }); + + // Register button click listener + buttonRegister.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + validateAndRegister(); + } + }); + } + + private void showDatePickerDialog() { + final Calendar calendar = Calendar.getInstance(); + int year = calendar.get(Calendar.YEAR); + int month = calendar.get(Calendar.MONTH); + int day = calendar.get(Calendar.DAY_OF_MONTH); + + DatePickerDialog datePickerDialog = new DatePickerDialog( + MainActivity.this, + new DatePickerDialog.OnDateSetListener() { + @Override + public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDay) { + // Month is 0-indexed, so add 1 + String date = selectedDay + "/" + (selectedMonth + 1) + "/" + selectedYear; + editTextDOB.setText(date); + } + }, + year, month, day + ); + datePickerDialog.show(); + } + + private void validateAndRegister() { + String name = editTextName.getText().toString().trim(); + String email = editTextEmail.getText().toString().trim(); + String dob = editTextDOB.getText().toString().trim(); + String password = editTextPassword.getText().toString().trim(); + int selectedGenderId = radioGroupGender.getCheckedRadioButtonId(); + + // Check fields from top to bottom, show only one toast at a time + if (name.isEmpty()) { + Toast.makeText(this, "Please enter your name", Toast.LENGTH_SHORT).show(); + return; + } + + if (email.isEmpty()) { + Toast.makeText(this, "Please enter your email address", Toast.LENGTH_SHORT).show(); + return; + } + + // Validate email format + if (!isValidEmail(email)) { + Toast.makeText(this, "Please enter a valid email address", Toast.LENGTH_SHORT).show(); + return; + } + + if (selectedGenderId == -1) { + Toast.makeText(this, "Please select your gender", Toast.LENGTH_SHORT).show(); + return; + } + + if (dob.isEmpty()) { + Toast.makeText(this, "Please select your date of birth", Toast.LENGTH_SHORT).show(); + return; + } + + if (password.isEmpty()) { + Toast.makeText(this, "Password should be at least 8 characters long", Toast.LENGTH_SHORT).show(); + return; + } + + // Validate password + if (password.length() < 8) { + Toast.makeText(this, "Password should be at least 8 characters long", Toast.LENGTH_SHORT).show(); + return; + } + + if (!isValidPassword(password)) { + Toast.makeText(this, "Password should contain 1 numeric digit, 1 uppercase letter, and 1 special character", Toast.LENGTH_SHORT).show(); + return; + } + + // Get selected gender text + RadioButton selectedGenderButton = findViewById(selectedGenderId); + String gender = selectedGenderButton.getText().toString(); + + // All validations passed — open second activity + Intent intent = new Intent(MainActivity.this, DisplayActivity.class); + intent.putExtra("name", name); + intent.putExtra("email", email); + intent.putExtra("gender", gender); + intent.putExtra("dob", dob); + startActivity(intent); + } + + private boolean isValidEmail(String email) { + // A valid email: username@domain.com + // Username: letters, numbers, underscores, periods, dashes + // Domain: multiple parts separated by dots + String emailPattern = "^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; + return Pattern.matches(emailPattern, email); + } + + private boolean isValidPassword(String password) { + // Must contain at least one numeric digit + boolean hasDigit = false; + // Must contain at least one uppercase letter + boolean hasUppercase = false; + // Must contain at least one special character from @#$%^&+=! + boolean hasSpecialChar = false; + + String specialCharacters = "@#$%^&+=!"; + + for (char c : password.toCharArray()) { + if (Character.isDigit(c)) { + hasDigit = true; + } else if (Character.isUpperCase(c)) { + hasUppercase = true; + } else if (specialCharacters.indexOf(c) != -1) { + hasSpecialChar = true; + } + } + + return hasDigit && hasUppercase && hasSpecialChar; + } +} diff --git a/Question1/app/src/main/res/drawable/app_logo.xml b/Question1/app/src/main/res/drawable/app_logo.xml new file mode 100644 index 0000000..c0a2487 --- /dev/null +++ b/Question1/app/src/main/res/drawable/app_logo.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/Question1/app/src/main/res/drawable/ic_calendar.xml b/Question1/app/src/main/res/drawable/ic_calendar.xml new file mode 100644 index 0000000..166caae --- /dev/null +++ b/Question1/app/src/main/res/drawable/ic_calendar.xml @@ -0,0 +1,11 @@ + + + + diff --git a/Question1/app/src/main/res/drawable/ic_email.xml b/Question1/app/src/main/res/drawable/ic_email.xml new file mode 100644 index 0000000..99b3389 --- /dev/null +++ b/Question1/app/src/main/res/drawable/ic_email.xml @@ -0,0 +1,11 @@ + + + + diff --git a/Question1/app/src/main/res/drawable/ic_lock.xml b/Question1/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 0000000..59c5d2b --- /dev/null +++ b/Question1/app/src/main/res/drawable/ic_lock.xml @@ -0,0 +1,11 @@ + + + + diff --git a/Question1/app/src/main/res/drawable/ic_person.xml b/Question1/app/src/main/res/drawable/ic_person.xml new file mode 100644 index 0000000..e8d8164 --- /dev/null +++ b/Question1/app/src/main/res/drawable/ic_person.xml @@ -0,0 +1,11 @@ + + + + diff --git a/Question1/app/src/main/res/layout/activity_display.xml b/Question1/app/src/main/res/layout/activity_display.xml new file mode 100644 index 0000000..77a0519 --- /dev/null +++ b/Question1/app/src/main/res/layout/activity_display.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Question1/app/src/main/res/layout/activity_main.xml b/Question1/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..9951831 --- /dev/null +++ b/Question1/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +