"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
- How it is built
- Repository layout
- Getting started
- API overview
- Project status
- Project background
- Team
What it does
The app shows a different menu depending on the role of the logged-in user.
| Role | What they can do |
|---|---|
| Student | Register 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 |
| Administrator | Create residences and rooms, review and accept or refuse applications, see all renters, payments and cleanings, chat with students |
| Cleaning staff | See 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
| Part | Technology |
|---|---|
| Android app | Kotlin, XML layouts, Retrofit + Gson, OkHttp, Room, Picasso, Firebase Messaging (min SDK 24) |
| API | Node.js, Express, Sequelize, express-ws, JSON Web Tokens |
| Database | Microsoft SQL Server |
| Push | Firebase Cloud Messaging (HTTP v1) |
| Tests | Jest + Supertest (API), JUnit + Espresso (app) |
| API specs | OpenAPI 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:
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
cd api
npm install
Copy .env.example to .env inside api/ and fill it in:
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
| Variable | Purpose |
|---|---|
PORT, HOST | Where the API listens. Both are required. |
HOST_URL | Public URL of the API |
SQL_SERVER, SQL_DATABASE, SQL_USER, SQL_PASSWORD | SQL Server connection |
ENCRYPT | true to encrypt the SQL connection (e.g. Azure) |
SECRET_TOKEN | Secret used to sign and verify JWTs |
FIREBASE_SERVICE_ACCOUNT | Path to a Firebase service account key (push) |
ADMIN_PASSWORD | Password given to the two admins created by setup |
Create the tables and the starting data, then start the API:
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
-
Open the
android/folder in Android Studio and let Gradle sync. -
Set the API address in GlobalVariables.kt:
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.2is 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. -
To use your own Firebase project, replace
android/app/google-services.jsonwith the one from your Firebase console. -
Run the
appconfiguration on an emulator or a device running Android 7.0 or newer.
Tests
cd api
npm test
API overview
All endpoints sit under /unihome/api. Each resource follows the same naming pattern:
| Action | Pattern | Example |
|---|---|---|
| List all | GET /list<Resource>s | GET /listResidences |
| Get one | GET /list<Resource>/:ID | GET /listRoom/3 |
| Create | POST /create<Resource> | POST /createCleaning |
| Update | PUT /update<Resource>/:ID | PUT /updateApplication/7 |
| Delete | DELETE /delete<Resource>/:ID | DELETE /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
POST /unihome/api/authLogin
Content-Type: application/json
{ "email": "student@example.com", "password": "..." }
Both authLogin and authRegister answer with a token:
{ "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:
{ "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
DeviceandDeviceTypeendpoints 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.