An Android application built in Kotlin that continuously reads real-time mobile hardware sensors (Accelerometer & Gyroscope), pushes timestamped data directly to Firebase Realtime Database, and visualizes historical cloud data using custom canvas charts.
This section details the step-by-step lifecycle of a sensor reading—from physical hardware motion to cloud persistence and real-time visualization—explaining exactly how each technology in the stack is utilized at each stage.
[ Hardware Sensors ]
│
▼ (Android SensorManager API)
[ SensorReader Listener ]
│
▼ (Volatile Vector3D Models)
[ Payload Builder ] ── (System.currentTimeMillis + Device ID)
│
▼ (Kotlin Coroutines & OkHttp REST)
[ Firebase Realtime Database ] ── (Stored as JSON Node /sensor_readings)
│
▼ (OkHttp GET Request & Gson Parser)
[ SimpleChartView Canvas ] ── (3-Axis X,Y,Z Line Charts)
- Technology Used:
Android SensorManager Framework&SensorEventListener - Mechanism:
SensorReaderacquires instances of the default hardware accelerometer (Sensor.TYPE_ACCELEROMETER) and gyroscope (Sensor.TYPE_GYROSCOPE) viaContext.getSystemService(Context.SENSOR_SERVICE).- When listening starts (
onResume),registerListenerregisters callbacks operating atSensorManager.SENSOR_DELAY_NORMAL. - Whenever physical movement occurs,
onSensorChanged(event: SensorEvent)triggers and extracts 3D axis floats (event.values[0],event.values[1],event.values[2]). - Extracted values are immediately saved into thread-safe
@VolatileVector3Dinstance properties (latestAccelandlatestGyro), ensuring lock-free, zero-latency access for background coroutines.
-
Technology Used:
Kotlin Coroutines(lifecycleScope),Gson -
Mechanism:
- The user configures an upload interval
$T$ (1 to 10 seconds) and presses Start Continuous Push. - A background coroutine is launched on
lifecycleScope.launch, running a periodicwhile (isActive)loop delayed by$T \times 1000\text{ ms}$ . - At every interval, a snapshot of the current sensor state is wrapped into a
SensorDataPayloaddata class containing:-
timestamp: Epoch milliseconds (System.currentTimeMillis()) -
deviceId: Unique device descriptor (Build.MANUFACTURER + "_" + Build.MODEL) -
accelerometer:Vector3D(x, y, z) -
gyroscope:Vector3D(x, y, z)
-
- Google
Gsonserializes this Kotlin data class into a clean JSON string payload.
- The user configures an upload interval
- Technology Used:
OkHttp 4HTTP Client,Firebase Realtime Database REST API - Mechanism:
- The app executes an asynchronous network call on
Dispatchers.IOusingOkHttp. - A
POSTHTTP request containing the JSON payload is dispatched tohttps://micro-project-c8bad-default-rtdb.firebaseio.com/sensor_readings.json. - If an optional authentication secret is provided, the query string
?auth=<token>is attached to satisfy Firebase Security Rules ("auth != null"). - Firebase assigns a unique push key (e.g.,
-O-a1b2c3d4e5f6) and persists the record under the/sensor_readingsnode. - The HTTP response status (
200 OKor401 Unauthorized) is returned and appended to the live UI upload log view inMainActivity.
- The app executes an asynchronous network call on
- Technology Used:
OkHttp 4,Gson TypeToken - Mechanism:
- In the Cloud Visualization tab (or when Auto Refresh is enabled), a
GETrequest fetches the latest records fromhttps://micro-project-c8bad-default-rtdb.firebaseio.com/sensor_readings.json. - Firebase responds with a JSON map of push key objects.
Gsondeserializes the JSON response map into aMap<String, SensorDataPayload>.- The payloads are sorted chronologically by
timestampand sliced to yield the most recent records for rendering.
- In the Cloud Visualization tab (or when Auto Refresh is enabled), a
-
Technology Used:
Custom Android View,Android Graphics Canvas & Paint APIs -
Mechanism:
- The sorted list of sensor payloads is passed to
SimpleChartView.setData(vectors). -
SimpleChartViewextendsandroid.view.Viewand overridesonDraw(canvas: Canvas). - Canvas coordinates are calculated dynamically based on view dimensions (
width,height). - Zero-reference axes and grid lines are drawn using
Paint. - Sequential sensor values are mapped onto the Canvas space:
-
Red Line:
$X$ -axis values -
Green Line:
$Y$ -axis values -
Blue Line:
$Z$ -axis values
-
Red Line:
-
canvas.drawLine()connects consecutive data points to render continuous 3-axis motion trajectory graphs for both Accelerometer and Gyroscope motion.
- The sorted list of sensor payloads is passed to
| Technology | Role in Stack | Specific Function / Usage |
|---|---|---|
| Android Sensor Framework | Hardware Integration | Reads physical device TYPE_ACCELEROMETER & TYPE_GYROSCOPE values |
| Kotlin Coroutines | Concurrency & Async | Schedules non-blocking periodic streaming loops & network requests |
| Google Gson | Data Serialization | Converts Kotlin data classes (SensorDataPayload) to/from JSON strings |
| OkHttp 4 | HTTP Networking | Sends REST POST push calls and GET fetch requests to Firebase |
| Firebase Realtime DB | Cloud Persistence | Stores timestamped sensor records in JSON trees |
| Custom Canvas View | Data Visualization | Draws multi-axis line graphs ( |
| Material Components | UI Design | Provides TabLayout, input controls, status labels, and activity structure |
Data stored in Firebase Realtime Database under /sensor_readings:
{
"-O6xY_abc123": {
"timestamp": 1700000000000,
"deviceId": "Google_Pixel_8",
"accelerometer": {
"x": -1.50,
"y": 3.37,
"z": 8.95
},
"gyroscope": {
"x": -0.02,
"y": -0.44,
"z": 0.18
}
}
}Endpoint URL: https://micro-project-c8bad-default-rtdb.firebaseio.com/
- Option A: Public Access (Recommended for testing)
In Firebase Console -> Realtime Database -> Rules:
{ "rules": { ".read": true, ".write": true } } - Option B: Authenticated Access
If
auth != nullrules are enabled, copy your Database Secret from Firebase Console -> Project Settings -> Service Accounts -> Database Secrets, and enter it into the Auth Secret field in the app UI.
# Clone the repository
git clone <repo-url>
cd <repo-folder>
# Run unit tests
./gradlew test
# Build debug APK
./gradlew assembleDebugThe pre-compiled executable APK is available at apk/app-debug.apk.
