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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Question1/app/src/main/res/values/colors.xml b/Question1/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..648cfde
--- /dev/null
+++ b/Question1/app/src/main/res/values/colors.xml
@@ -0,0 +1,9 @@
+
+
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
diff --git a/Question1/app/src/main/res/values/strings.xml b/Question1/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..d4ab170
--- /dev/null
+++ b/Question1/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ RegistrationApp
+
diff --git a/Question1/build.gradle b/Question1/build.gradle
new file mode 100644
index 0000000..8df2f08
--- /dev/null
+++ b/Question1/build.gradle
@@ -0,0 +1,4 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '8.2.0' apply false
+}
diff --git a/Question1/gradle.properties b/Question1/gradle.properties
new file mode 100644
index 0000000..3c5e113
--- /dev/null
+++ b/Question1/gradle.properties
@@ -0,0 +1,2 @@
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+android.useAndroidX=true
diff --git a/Question1/settings.gradle b/Question1/settings.gradle
new file mode 100644
index 0000000..2f057a6
--- /dev/null
+++ b/Question1/settings.gradle
@@ -0,0 +1,17 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "RegistrationApp"
+include ':app'
diff --git a/Question2/app/build.gradle b/Question2/app/build.gradle
new file mode 100644
index 0000000..0de56e5
--- /dev/null
+++ b/Question2/app/build.gradle
@@ -0,0 +1,35 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace 'com.example.mapwebapp'
+ compileSdk 36
+
+ defaultConfig {
+ applicationId "com.example.mapwebapp"
+ 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'
+ implementation 'com.google.android.gms:play-services-maps:18.2.0'
+}
diff --git a/Question2/app/src/main/AndroidManifest.xml b/Question2/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d75d270
--- /dev/null
+++ b/Question2/app/src/main/AndroidManifest.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Question2/app/src/main/java/com/example/mapwebapp/MainActivity.java b/Question2/app/src/main/java/com/example/mapwebapp/MainActivity.java
new file mode 100644
index 0000000..b79e5f2
--- /dev/null
+++ b/Question2/app/src/main/java/com/example/mapwebapp/MainActivity.java
@@ -0,0 +1,40 @@
+package com.example.mapwebapp;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+public class MainActivity extends AppCompatActivity {
+
+ private Button buttonOpenWebsite, buttonOpenMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ buttonOpenWebsite = findViewById(R.id.buttonOpenWebsite);
+ buttonOpenMap = findViewById(R.id.buttonOpenMap);
+
+ // Open Website button click
+ buttonOpenWebsite.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
+ startActivity(intent);
+ }
+ });
+
+ // Open Map button click
+ buttonOpenMap.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(MainActivity.this, MapsActivity.class);
+ startActivity(intent);
+ }
+ });
+ }
+}
diff --git a/Question2/app/src/main/java/com/example/mapwebapp/MapsActivity.java b/Question2/app/src/main/java/com/example/mapwebapp/MapsActivity.java
new file mode 100644
index 0000000..3796b22
--- /dev/null
+++ b/Question2/app/src/main/java/com/example/mapwebapp/MapsActivity.java
@@ -0,0 +1,49 @@
+package com.example.mapwebapp;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.gms.maps.CameraUpdateFactory;
+import com.google.android.gms.maps.GoogleMap;
+import com.google.android.gms.maps.OnMapReadyCallback;
+import com.google.android.gms.maps.SupportMapFragment;
+import com.google.android.gms.maps.model.LatLng;
+import com.google.android.gms.maps.model.MarkerOptions;
+
+public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
+
+ private GoogleMap mMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_maps);
+
+ // Obtain the SupportMapFragment and get notified when the map is ready to be used
+ SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
+ .findFragmentById(R.id.map);
+ mapFragment.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(GoogleMap googleMap) {
+ mMap = googleMap;
+
+ // Define the three locations
+ LatLng kelowna = new LatLng(49.8801, -119.4436);
+ LatLng ubco = new LatLng(49.9394, -119.3948);
+ LatLng lakeCountry = new LatLng(50.0537, -119.4106);
+
+ // Add markers with titles (shown when marker is clicked)
+ mMap.addMarker(new MarkerOptions().position(kelowna).title("Kelowna"));
+ mMap.addMarker(new MarkerOptions().position(ubco).title("UBCO"));
+ mMap.addMarker(new MarkerOptions().position(lakeCountry).title("Lake Country"));
+
+ // Move camera to Kelowna with zoom level 10
+ mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(kelowna, 10));
+
+ // Enable zoom controls (Zoom in/out buttons at bottom-right corner)
+ mMap.getUiSettings().setZoomControlsEnabled(true);
+ }
+}
diff --git a/Question2/app/src/main/java/com/example/mapwebapp/WebViewActivity.java b/Question2/app/src/main/java/com/example/mapwebapp/WebViewActivity.java
new file mode 100644
index 0000000..91d0805
--- /dev/null
+++ b/Question2/app/src/main/java/com/example/mapwebapp/WebViewActivity.java
@@ -0,0 +1,41 @@
+package com.example.mapwebapp;
+
+import android.os.Bundle;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+public class WebViewActivity extends AppCompatActivity {
+
+ private WebView webView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_webview);
+
+ webView = findViewById(R.id.webView);
+
+ // Enable JavaScript
+ WebSettings webSettings = webView.getSettings();
+ webSettings.setJavaScriptEnabled(true);
+
+ // Make links open within the WebView instead of the browser
+ webView.setWebViewClient(new WebViewClient());
+
+ // Load the UBCO website
+ webView.loadUrl("https://www.ubc.ca/okanagan/");
+ }
+
+ @Override
+ public void onBackPressed() {
+ // Allow navigating back within the WebView
+ if (webView.canGoBack()) {
+ webView.goBack();
+ } else {
+ super.onBackPressed();
+ }
+ }
+}
diff --git a/Question2/app/src/main/res/layout/activity_main.xml b/Question2/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..957db49
--- /dev/null
+++ b/Question2/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Question2/app/src/main/res/layout/activity_maps.xml b/Question2/app/src/main/res/layout/activity_maps.xml
new file mode 100644
index 0000000..7afc772
--- /dev/null
+++ b/Question2/app/src/main/res/layout/activity_maps.xml
@@ -0,0 +1,9 @@
+
+
diff --git a/Question2/app/src/main/res/layout/activity_webview.xml b/Question2/app/src/main/res/layout/activity_webview.xml
new file mode 100644
index 0000000..f522d80
--- /dev/null
+++ b/Question2/app/src/main/res/layout/activity_webview.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/Question2/app/src/main/res/values/colors.xml b/Question2/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..648cfde
--- /dev/null
+++ b/Question2/app/src/main/res/values/colors.xml
@@ -0,0 +1,9 @@
+
+
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
diff --git a/Question2/app/src/main/res/values/strings.xml b/Question2/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..d84cdf0
--- /dev/null
+++ b/Question2/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ MapWebApp
+
diff --git a/Question2/build.gradle b/Question2/build.gradle
new file mode 100644
index 0000000..8df2f08
--- /dev/null
+++ b/Question2/build.gradle
@@ -0,0 +1,4 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '8.2.0' apply false
+}
diff --git a/Question2/gradle.properties b/Question2/gradle.properties
new file mode 100644
index 0000000..3c5e113
--- /dev/null
+++ b/Question2/gradle.properties
@@ -0,0 +1,2 @@
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+android.useAndroidX=true
diff --git a/Question2/settings.gradle b/Question2/settings.gradle
new file mode 100644
index 0000000..5e1f9d4
--- /dev/null
+++ b/Question2/settings.gradle
@@ -0,0 +1,17 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "MapWebApp"
+include ':app'