A comprehensive Android application suite built with Java that solves real-world mobile tracking and sensor data collection challenges. The project demonstrates advanced Java concepts including service-oriented architecture, concurrent programming, event-driven design patterns, and hardware abstraction through Android's sensor framework.
Challenge: Mobile apps typically pause when users switch to other apps, causing gaps in sensor data collection critical for tracking applications.
Java Solution - Android Service Architecture:
- Implemented 5 independent
Serviceclasses extendingandroid.app.Service - Each service runs in the background independently of the UI lifecycle
- Services continue data collection even when the app is minimized
Implementation Details:
public class AccelerometerService extends Service implements SensorEventListener {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// START_STICKY ensures service restarts if killed by system
return START_STICKY;
}
}Key Java Concepts Demonstrated:
- Inheritance: Each sensor service extends the base
Serviceclass - Interface Implementation: Services implement
SensorEventListenerfor sensor callbacks - Lifecycle Management: Override
onStartCommand(),onDestroy()for proper resource management
Challenge: Raw accelerometer data includes gravity force (9.8 m/s²), making motion detection inaccurate.
Java Solution - Digital Signal Processing:
// Low-pass filter to isolate gravity
private final float alpha = 0.9f;
gravityForce[0] = alpha * gravityForce[0] + (1 - alpha) * sensorEvent.values[0];
// High-pass filter to remove gravity
float x = sensorEvent.values[0] - gravityForce[0];Technical Implementation:
- Applied complementary filters (low-pass + high-pass) in real-time
- Calculated motion magnitude using vector mathematics
- Implemented threshold-based event filtering (delta > 0.5) to reduce noise
Challenge: Sensor events fire 50-100 times/second, requiring efficient file I/O without blocking the UI.
Java Solution - Buffered File Operations:
public class RWFiles {
public void write(String fileName, String data, Context ctx) {
FileOutputStream fos = new FileOutputStream(file, true); // Append mode
fos.write(data.getBytes());
}
}Optimizations Implemented:
- Time-based throttling: Only write when
(System.currentTimeMillis() - lastUpdate) > 100 - Magnitude-based filtering: Only log significant changes (delta > 0.5)
- CSV format for minimal storage overhead
- Proper resource management with try-finally blocks
Challenge: Different sensors update at different rates; GPS at 1Hz, accelerometer at 50Hz, requiring coordination.
Java Solution - Event-Driven Architecture:
// Main activity manages multiple services
public void onClickAcc(View view) {
Intent service = new Intent(getApplicationContext(), AccelerometerService.class);
switch (view.getId()) {
case R.id.startAccelerometer:
this.startService(service);
btnsacc.setEnabled(false); // UI state management
break;
}
}Design Patterns Used:
- Observer Pattern: SensorEventListener for asynchronous updates
- Command Pattern: Intent-based service control
- Singleton Pattern: SensorManager system service access
Challenge: Android 6.0+ requires runtime permissions for location access.
Java Solution - Runtime Permission Handling:
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "you need permissions from the user", Toast.LENGTH_LONG);
} else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
}Challenge: Display live GPS position on interactive map with smooth updates.
Java Solution - Google Maps Integration:
public class MapsActivity extends FragmentActivity
implements OnMapReadyCallback, LocationListener {
@Override
public void onLocationChanged(Location location) {
LatLng myloc = new LatLng(location.getLatitude(), location.getLongitude());
marker.setPosition(myloc);
mMap.moveCamera(CameraUpdateFactory.newLatLng(myloc));
}
}Advanced Features:
- Asynchronous map loading with callbacks
- Marker position updates without recreating objects (memory efficient)
- Camera animation for smooth transitions
MainActivity (UI Thread)
├── AccelerometerService (Background)
├── GyroscopeService (Background)
├── CompassService (Background)
├── GpsService (Background)
└── BarometerService (Background)
- Sensor Registration: Services register with SensorManager at startup
- Event Handling: onSensorChanged() callbacks process raw data
- Data Processing: Apply filters, calculate derived values
- Persistence: Write to CSV files on external storage
- UI Updates: Services operate independently of UI lifecycle
- SensorManager: Hardware sensor access and event registration
- LocationManager: GPS provider management and location updates
- Service: Background task execution independent of UI
- Intent: Inter-component communication and service control
- Interfaces:
SensorEventListener,LocationListenerfor callbacks - Inheritance: Custom services extending base Service class
- Exception Handling: Try-catch-finally for file operations
- Generics: Used in Android collections and adapters
- Anonymous Inner Classes: Click listeners and callbacks
- Observer Pattern: Sensor event listeners
- Singleton Pattern: System service access
- Template Method: Service lifecycle methods
- Strategy Pattern: Different sensor processing algorithms
- Reuse marker objects instead of creating new ones
- Proper listener unregistration in onDestroy()
- File stream closure in finally blocks
- SENSOR_DELAY_UI instead of SENSOR_DELAY_FASTEST
- 1-second GPS update interval
- Conditional logging based on movement threshold
- Services handle concurrent sensor events
- File writes use append mode to avoid conflicts
- UI updates dispatched to main thread
String ss = String.format("%f | %f | %f",
sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2]);
// Toast.makeText(this, ss, Toast.LENGTH_LONG).show();- Timestamped data for correlation analysis
- Headers for easy import into analysis tools
- Separate files per sensor for isolation
- Service-Oriented Architecture: Designed modular, loosely-coupled services
- Event-Driven Programming: Extensive use of listeners and callbacks
- Resource Management: Proper lifecycle handling and cleanup
- Performance Awareness: Implemented throttling and filtering
- Android Platform Knowledge: Deep understanding of Android components
- Problem-Solving: Applied DSP algorithms for sensor data processing
- Design Patterns: Practical application of GoF patterns
- File I/O: Efficient data persistence strategies
- Concurrent Programming: Handled multiple asynchronous data streams
- API Integration: Google Maps SDK integration with custom overlays
- Why Services over Threads? Services survive configuration changes and provide system-managed lifecycle
- Why CSV over database? Portability for data analysis in Python/MATLAB
- Why separate services? Modularity and independent failure handling
- Could implement WorkManager for battery-optimized scheduling
- Could add data compression for long-term recording
- Could implement cloud sync for multi-device scenarios
- Java 8+ lambdas for listeners (if min SDK allowed)
- CompletableFuture for async operations
- Stream API for data processing
- Optional for null safety
This project demonstrates comprehensive Java knowledge through practical Android implementation, showing ability to architect complex systems, handle concurrent operations, and solve real-world problems using Java's object-oriented paradigm.