Projects

CyberPlatter Android Recipe Manager

Historical CMP309 Android coursework demonstrating Firebase-backed sign-in and a local SQLite create, search, view, update, and delete workflow.

  • Android
  • Java
  • SQLite
  • Firebase Authentication
  • Object-oriented design
On this page

Project snapshot

Authorised scope
Individual CMP309 Android Development project presented through a final 162-second emulator demonstration and architecture and execution-flow diagrams.
My contribution
I designed and implemented the activity flow, Firebase login and registration paths, recipe model, and SQLite helper.
Technical focus
  • Android activity flow
  • Firebase Authentication
  • SQLite CRUD
  • Local data modelling
  • Search and record navigation
Demonstrated outcome
The 162-second demonstration shows successful sign-in followed by recipe creation, full-list and query-based retrieval, record viewing, update, deletion, and a refreshed result list. It does not demonstrate successful registration, persistence across a restart, or multi-device use.

Why I am keeping this project

CyberPlatter was my 2023 CMP309 Android Development project: a personal recipe manager with Firebase Authentication for identity and an on-device SQLite database for recipe records.

It was also the first project I completed without feeling confident in the result. I was dissatisfied with parts of the design when I finished it, and I do not want to rewrite that experience as a polished product story. Its value is narrower and more honest: I completed a working local data flow, attempted to separate interface and storage responsibilities, and could already identify problems in my own implementation.

I used a 19-slide presentation, code excerpts, architecture diagrams and a 162-second emulator recording to demonstrate the application. This retrospective distinguishes between:

  • behaviour visible in the demonstration;
  • implementation documented by the diagrams and code screenshots; and
  • improvements that were only proposed.

An earlier concept note described categories, network downloads, a content provider, cloud preferences, and social sharing. Those features do not appear in the final architecture or demonstration and are not presented as completed work.

What I set out to build

The final application was smaller than that early concept. A user could enter through login or registration, reach a main page, add recipes, browse or search stored entries, open one record, and then update or delete it.

Each recipe contained five values in the documented RecipeModal class:

  • name;
  • description;
  • ingredients;
  • method; and
  • a database identifier.

Firebase handled account identity. Recipe contents were stored separately in a local SQLite database named Recipe.db. The recipe model did not include a user identifier, so I cannot claim that local records were partitioned or access-controlled by Firebase account.

Architecture and execution flow

The original architecture diagram separated Android presentation files from two data-handling classes. The execution-flow diagram added the external Firebase dependency and the local SQLite database.

Recreated CyberPlatter architecture showing LoginActivity and RegisterActivity using Firebase Authentication, recipe activities passing data through RecipeModal and DBHandler, and DBHandler querying the local SQLite Recipe.db database
The architecture I presented for CyberPlatter: Firebase handled identity, Android activities handled the interface flow, and DBHandler connected the recipe model to local SQLite storage.

The activity layer contained two related flows:

LoginActivity <-> RegisterActivity
       |
       v
Firebase Authentication
       |
       v
MainActivity
   |          |
   v          v
AddActivity  SearchActivity -> ViewRecipe -> UpdateActivity

The presentation describes RecipeModal as the object passed into data operations. DBHandler owned the SQLite schema and the documented insert, lookup, update, delete, and list queries. That kept SQL access out of the individual activity descriptions and gave the interface layer a common route into local storage.

I structured the main components around these responsibilities:

Component Documented responsibility
RecipeModal Store the recipe name, description, ingredients, method, and ID behind getters and setters
DBHandler.onCreate Create the recipe table and its initial columns
DBHandler.onUpgrade Drop the existing table and recreate it when the database version changes
Insert and list queries Add a recipe and populate the search/list view
CheckDetails Return one selected recipe as a RecipeModal object
Update and delete operations Modify or remove the row represented by a selected recipe object

The upgrade behaviour is a particularly important boundary. Dropping and recreating the table is simple during coursework development, but it destroys existing data rather than migrating it. The presentation correctly identified non-destructive migration as future work.

What the demonstration actually shows

The 162-second emulator recording shows state changing across one continuous session.

Demonstrated stage Observation in the recording What it supports
Entry and identity The registration screen opens, the flow returns to login, and submitted credentials reach the main page Login and navigation worked for the demonstrated account; successful account creation was not shown
Create Two sample recipes are entered through the add screen and then appear in the recipe list Insert and list retrieval worked in that session
Search The list first shows all stored entries and then narrows after a query Both full-list and query-based retrieval were exercised
Read Selecting a result opens its name, description, ingredients, and method A selected database record could be retrieved and presented
Update One record is edited, renamed, and shown with the changed values The update path wrote changes that were visible to a later read
Delete The updated record is removed; the interface reports one affected recipe and the refreshed list contains the remaining entry The delete path changed the local data set and the subsequent query reflected it

In sequence, the demonstrated path was:

successful login
    -> main page
    -> create two recipes
    -> list and search stored recipes
    -> open one recipe
    -> update and re-read it
    -> delete it
    -> confirm the remaining list

This demonstrated a complete CRUD path inside one running emulator session. I did not test restart persistence, offline behaviour, successful new-account registration, invalid-input handling, multi-user isolation, concurrent access, device compatibility, or a clean reproducible build.

Where the design fell short

The final presentation included a critical analysis rather than claiming the application was finished. Its most important limitations were:

  • Destructive upgrades. Changing the database version dropped the table instead of preserving and migrating existing records.
  • Weak validation. Duplicate recipes and other invalid inputs needed clearer rejection and error handling.
  • No recovery path. Local records had no backup or restore mechanism, so losing or replacing the device could also lose the recipe collection.
  • No synchronisation. Firebase authenticated the user but did not synchronise recipe data between devices.
  • Unverified account separation. The recipe model had no user identifier, so I did not demonstrate recipe ownership being enforced per authenticated account.
  • Readable local storage. The presentation identified at-rest database encryption as future work; the implemented database was not described as encrypted.
  • Static layouts. The add and update screens could overflow on different display sizes and needed scrolling and more responsive layout behaviour.
  • Coarse data modelling. Ingredients were stored as one field. Quantities, prices, shopping lists, and meal planning would have required a separate related structure rather than more text parsing.
  • No reproducibility test. I did not demonstrate a clean build, automated test suite or dependency-locked setup, so the project should not be treated as reproducible from a fresh environment.

I occasionally described the database as reliable, efficient or secure, but I did not perform the testing needed for those claims. The demonstrated result was a functioning local CRUD workflow, not measured performance, security, reliability or production readiness.

What I would change before treating it as a serious application

The first change would be to define the data and identity rules before adding more screens. If authentication is part of the product, the design should state whether recipes belong to a device, an account, or both, and the schema and access path should enforce that decision.

I would then replace destructive upgrades with versioned migrations, introduce field and uniqueness constraints, define observable failure states, and test create, search, update, delete, restart, and upgrade behaviour independently. Backup and synchronisation would need a conflict model rather than simply copying the SQLite file between devices.

The interface would also need to be tested across screen sizes and content lengths. Long ingredients and methods are normal recipe data, so scrolling, saved form state, and interruption during editing should be requirements rather than later fixes.

Finally, I would make reproducibility part of the definition of done: dependency locking, automated tests and a clean build from a fresh checkout rather than relying on one successful emulator session.

What the project demonstrates now

CyberPlatter should not be read as my current Android engineering standard. It is a bounded historical project showing that I implemented and demonstrated an authenticated, multi-screen CRUD application while still making several weak architectural and validation choices.

The useful progression is not that every part succeeded. Remote identity and local recipe storage were connected through the interface, the full record lifecycle worked in one emulator session, and the surrounding ownership, migration, recovery, validation and testing design remained incomplete.