← All projects

UniHome

An Android app for university residences. Students apply for a room, open the door from their phone, set the air conditioning, pay rent and message the residence admin.

"To provide a way to be a second home."

UniHome is an Android app, backed by a REST API, for running a university residence. Students apply for a room, pay their rent, book cleanings and talk to the residence staff; administrators review applications, manage residences and rooms, and keep track of renters and payments.

It was built as an academic project by a team of four, working in Scrum.

Contents

What it does

The app shows a different menu depending on the role of the logged-in user.

RoleWhat they can do
StudentRegister and log in, browse residences, choose a room type and apply, see their room, pay rent and extra fees, book a cleaning, chat with the residence, edit their profile
AdministratorCreate residences and rooms, review and accept or refuse applications, see all renters, payments and cleanings, chat with students
Cleaning staffSee the list of booked cleanings and mark them as done

Other behaviour worth knowing:

  • Chat is real time. Messages travel over a WebSocket, and the other participants get a push notification through Firebase Cloud Messaging.
  • Every new user gets two chats on registration: one for general notifications and one private chat with the residence.
  • A student can only have one application at a time. The API rejects a second one.
  • Some data is cached on the device (user, room types, messages) in a local Room database.

How it is built

flowchart LR
    App["Android app<br/>(Kotlin)"]
    API["REST API<br/>(Node.js + Express)"]
    DB[("SQL Server")]
    FCM["Firebase Cloud<br/>Messaging"]

    App -- "HTTPS + JWT<br/>/unihome/api" --> API
    App <-- "WebSocket<br/>/unihome/ws/:chatID" --> API
    API -- "Sequelize" --> DB
    API -- "send notification" --> FCM
    FCM -- "push" --> App
PartTechnology
Android appKotlin, XML layouts, Retrofit + Gson, OkHttp, Room, Picasso, Firebase Messaging (min SDK 24)
APINode.js, Express, Sequelize, express-ws, JSON Web Tokens
DatabaseMicrosoft SQL Server
PushFirebase Cloud Messaging (HTTP v1)
TestsJest + Supertest (API), JUnit + Espresso (app)
API specsOpenAPI YAML, one file per resource

The API follows the same layering for every resource: routes → controllers → services → models. Role checks are done in middleware attached to each route.

Repository layout

.
├── api/                  Node.js REST API
│   ├── app.js            Express app and route registration
│   ├── server.js         Entry point
│   ├── config.js         Reads settings from .env
│   ├── sequelize.js      Database connection
│   ├── routes/           URL definitions, one file per resource
│   ├── controllers/      Request and response handling
│   ├── services/         Database access and business rules
│   ├── sockets/          Chat WebSocket
│   ├── models/           Sequelize models (one per table)
│   ├── middleware/       Role checks and the one-application rule
│   ├── specsOpenAPI/     OpenAPI description of each resource
│   ├── scripts/          Database setup and demo data
│   ├── utils/            Status and role enums, Firebase access token helper
│   ├── secrets/          Firebase key (ignored by git, you create it)
│   ├── .env.example      Template for the .env file
│   └── tests/            Jest tests
├── android/              Android Studio project
│   └── app/src/main/java/com/example/unihome/
│       ├── *Activity.kt  One activity per screen
│       ├── adapters/     List adapters
│       ├── services/     Retrofit interfaces for the API
│       ├── models/       Data classes returned by the API
│       ├── entities/     Room entities (local cache)
│       ├── daos/         Room DAOs
│       └── utils/        API URL, Retrofit builder, local database
└── docs/                 Planning material (Visual Paradigm model, early notes)

Getting started

You need the API running before the app can do anything.

Requirements

  • Node.js 18 or newer
  • A Microsoft SQL Server instance you can reach
  • Android Studio (the project uses Gradle 8.2, Kotlin 1.9 and compile SDK 34)
  • A Firebase project with Cloud Messaging enabled, if you want push notifications

1. Database

You need a SQL Server instance with an empty database. The quickest way is Docker:

bash
docker run -d --name unihome-db --platform linux/amd64 \
  -e ACCEPT_EULA=Y -e MSSQL_SA_PASSWORD='<a strong password>' \
  -p 1433:1433 -v unihome-db-data:/var/opt/mssql \
  mcr.microsoft.com/mssql/server:2022-latest

docker exec unihome-db /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P '<a strong password>' -C \
  -Q "CREATE DATABASE UniHome"

The tables and starting data are created from the API in the next step.

2. API

bash
cd api
npm install

Copy .env.example to .env inside api/ and fill it in:

ini
PORT=8080
HOST=localhost
HOST_URL=http://localhost:8080

SQL_SERVER=localhost
SQL_DATABASE=UniHome
SQL_USER=your_user
SQL_PASSWORD=your_password
ENCRYPT=false

SECRET_TOKEN=a-long-random-string

FIREBASE_SERVICE_ACCOUNT=./secrets/firebase-key.json

ADMIN_PASSWORD=password-for-the-first-admins
VariablePurpose
PORT, HOSTWhere the API listens. Both are required.
HOST_URLPublic URL of the API
SQL_SERVER, SQL_DATABASE, SQL_USER, SQL_PASSWORDSQL Server connection
ENCRYPTtrue to encrypt the SQL connection (e.g. Azure)
SECRET_TOKENSecret used to sign and verify JWTs
FIREBASE_SERVICE_ACCOUNTPath to a Firebase service account key (push)
ADMIN_PASSWORDPassword given to the two admins created by setup

Create the tables and the starting data, then start the API:

bash
npm run db:setup
npm start

db:setup builds the tables from the models in api/models/ and inserts the room, device, payment and chat types the API refers to by ID. On an empty database it also creates two administrators, admin1@unihome.local and admin2@unihome.local, with the password from ADMIN_PASSWORD. It is safe to run again.

To try the app with something in it, npm run db:seed adds fictional demo data: three residences with rooms and devices, thirteen students (some renting, some with applications to review), payments, cleanings and chat messages. Demo students log in with <name>.<surname>@unihome.local and the password unihome123.

The API is now at http://localhost:8080/unihome/api.

For push notifications, generate a service account key for your own Firebase project (Project settings → Service accounts), save it in api/secrets/ (a folder git ignores), and point FIREBASE_SERVICE_ACCOUNT at it. Never commit this file.

3. Android app

  1. Open the android/ folder in Android Studio and let Gradle sync.

  2. Set the API address in GlobalVariables.kt:

    kotlin
    const val UNIHOME_URL = "http://10.0.2.2:8080/unihome/api/"
    const val UNIHOME_WEB_SOCKET = "ws://10.0.2.2:8080/unihome/ws/"
    

    10.0.2.2 is how the Android emulator reaches your computer. On a physical phone, use your computer's address on the local network, or a tunnel such as ngrok.

  3. To use your own Firebase project, replace android/app/google-services.json with the one from your Firebase console.

  4. Run the app configuration on an emulator or a device running Android 7.0 or newer.

Tests

bash
cd api
npm test

API overview

All endpoints sit under /unihome/api. Each resource follows the same naming pattern:

ActionPatternExample
List allGET /list<Resource>sGET /listResidences
Get oneGET /list<Resource>/:IDGET /listRoom/3
CreatePOST /create<Resource>POST /createCleaning
UpdatePUT /update<Resource>/:IDPUT /updateApplication/7
DeleteDELETE /delete<Resource>/:IDDELETE /deleteRoom/3

Resources: User, Residence, ResidenceAdmin, Room, RoomType, Application, Rent, Payment, PaymentType, Cleaning, Chat, ChatType, Participant, Message, Device, DeviceType.

With the API running, the interactive documentation (Swagger UI) is at http://localhost:8080/unihome/docs. It is built from the files in api/specsOpenAPI/. To call protected endpoints there, log in through /authLogin, press Authorize and paste the token.

Authentication

http
POST /unihome/api/authLogin
Content-Type: application/json

{ "email": "student@example.com", "password": "..." }

Both authLogin and authRegister answer with a token:

json
{ "Authorization": "<jwt>" }

Send it in the Authorization header of every other request. Reading residences, room types, payment types, chat types and device types needs no token. Everything else requires a role of student, cleaning staff or administrator, depending on the route.

Chat WebSocket

Connect to ws://<host>/unihome/ws/<chatID> and send a message as JSON:

json
{ "ChatID": 12, "UserID": 4, "text": "Hello" }

The API stores the message, sends it to everyone connected to that chat, and pushes a notification to the other participants.

Project status

This is a course project and is not production ready. What exists today:

  • Working: registration and login, residences, room types and rooms, applications, rents, payments, cleaning bookings, real-time chat with push notifications, profile editing, role-based menus.
  • Simulated: payments. Pressing Pay marks the payment as paid; no payment provider is involved.
  • Planned, not built in the app: the smart room features from the original vision — opening the door with a smart lock, controlling heating and blinds, and locker delivery alerts. The API already has Device and DeviceType endpoints for them, but the My Room screen does not use them yet.
  • Not done: profile photo upload and meaningful automated test coverage.

Project background

Business context

UniHome was imagined as a product of Campex, a fictional housing company that wants to make university residences easier to run by putting everything related to the residence in one app.

Administrators manage who enters the residence, and students apply for rooms. Once accepted, a student uses the app for the day-to-day: paying rent, booking an optional paid cleaning, and reaching the administrator through chat about problems or requests. The administrator can reach students the same way.

The longer-term idea is a room controlled from the phone: a smart lock instead of physical keys, smart air conditioning for a comfortable room in any season, and a notification when a parcel arrives in the room's locker.

For students, this means more convenience and security. For universities, it is a way to attract students and give them a more comfortable place to focus on their studies.

Academic goals

The project was a chance to apply what we learned in class: planning, managing and delivering a project from start to finish, working as a team, and using an agile method (Scrum) to organise the work.