The Android version of PunctuOwlity is a Java app built with Android Studio, targeting API 35 with a minimum of API 21, using SQLite for local storage via a customDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/punctuowlity/llms.txt
Use this file to discover all available pages before exploring further.
DatabaseHelper class and Material3 for theming. All business logic, navigation, and data persistence are handled inside the Activity layer — there are no Fragments, ViewModels, or repositories.
Project Structure
All source files live under the packagecom.example.punctuowlityeventtracker. The package contains seven classes in total:
| Class | Role |
|---|---|
LoginActivity | Launcher activity — username/password sign-in |
SignupActivity | New-account registration |
SmsPermissionActivity | Runtime SEND_SMS permission request |
MainActivity | Main event list dashboard |
AddEventActivity | Create or edit a single event |
DatabaseHelper | SQLite SQLiteOpenHelper wrapper |
Event | Plain data model for a single event row |
Gradle highlights
gradle/libs.versions.toml) to pin dependency versions. Java source and target compatibility are set to JavaVersion.VERSION_11.
Activity Reference
LoginActivity
Purpose: Entry point of the application. Accepts a username and password, validates them against the SQLiteusers table, and navigates to MainActivity on success.
Layout: activity_login.xml
Key UI elements:
editUsername(EditText) — username inputeditPassword(EditText) — password inputbuttonLogin(Button) — submits credentialsbuttonSignUp(Button) — navigates toSignupActivity
- Login button → calls
DatabaseHelper.checkUser(username, password). Ontrue, startsMainActivityand callsfinish(). - Sign Up button → starts
SignupActivity. - A failed login shows a short
Toast:"Invalid Username or Password".
SignupActivity
Purpose: New-account registration screen. Collects an email address (used as the username) plus a password with a confirmation check, then inserts the credentials into the SQLiteusers table.
Layout: activity_signup.xml
Key UI elements:
editEmail(EditText) — taken as the username stored in the databaseeditPassword(EditText) — desired passwordeditConfirmPassword(EditText) — password confirmationbuttonCreateAccount(Button) — triggers registration
- Create Account button → validates that both password fields match, then calls
DatabaseHelper.insertUser(username, password). On success, shows"Account Created Successfully"and redirects toLoginActivity. On failure (e.g. duplicate username), shows"Account creation failed!".
SmsPermissionActivity
Purpose: Displayed whenMainActivity detects that the SEND_SMS permission has not been granted. Presents the user with an explicit Allow or Deny choice before proceeding to the main screen.
Layout: activity_sms.xml
Key UI elements:
buttonAllow(Button) — requests theSEND_SMSruntime permission viaActivityCompat.requestPermissionsbuttonDeny(Button) — skips the permission request and proceeds directly
goToMainActivity(), which starts MainActivity and finishes SmsPermissionActivity. If the Allow path triggers an OS permission dialog, onRequestPermissionsResult calls goToMainActivity() regardless of whether the user granted or denied.
MainActivity
Purpose: The primary event list screen. Loads all events from SQLite into aGridLayout using inflated event_card views, and provides edit and delete actions per card.
Layout: activity_main.xml
Key UI elements:
eventsGrid(GridLayout) — host for dynamically inflatedevent_cardviewsfabAddEvent(Floating Action Button) — navigates toAddEventActivityfor a new event
DatabaseHelper, calls loadEvents(), wires the FAB, and checks whether SEND_SMS is granted. If not, immediately starts SmsPermissionActivity (without finishing MainActivity, so the back stack is preserved).
loadEvents() method:
loadEvents() is also called from onResume() so the list refreshes automatically after returning from AddEventActivity.
AddEventActivity
Purpose: Handles both creating a new event and editing an existing one. The caller signals edit mode by including an"event_id" Intent extra; without it the activity creates a new event.
Layout: activity_add_event.xml
Key UI elements:
editEventTitle(EditText) — event titletextEventDate(EditText) — event date (displayed/entered as text)textEventTime(EditText) — event time (displayed/entered as text)buttonSave(Button) — saves the eventimageButton(ImageButton) — back button, callsfinish()
"event_id" is present in the incoming Intent, the activity calls db.getEventById(eventId) and pre-populates all three fields with the existing values.
Permissions and Manifest
android.hardware.telephony is declared with android:required="false" so that the app can be installed on tablets and emulators that do not have a cellular radio. The SEND_SMS permission is still declared and requested at runtime, but its absence does not prevent the app from running.
Only LoginActivity is exported and set as the launcher entry point. All other activities are internal (android:exported="false").
Dependencies
Key runtime dependencies declared inbuild.gradle (versions resolved via gradle/libs.versions.toml):
| Artifact | Version | Purpose |
|---|---|---|
androidx.appcompat:appcompat | 1.7.0 | AppCompatActivity base class for all activities |
com.google.android.material:material | 1.12.0 | Material Design widgets (buttons, cards, FAB) |
androidx.activity:activity | 1.8.0 | ComponentActivity and result APIs |
androidx.constraintlayout:constraintlayout | 2.1.4 | Constraint-based layouts |
androidx.gridlayout:gridlayout | 1.1.0 | GridLayout used in MainActivity for the event grid |
androidx.legacy:legacy-support-v4 | 1.0.0 | Backward-compatibility utilities |
androidx.lifecycle:lifecycle-runtime-ktx | 2.8.7 | Lifecycle-aware coroutine scopes |
androidx.compose.material3:material3 | (BOM 2024.09.00) | Material3 theming tokens via Compose BOM |