Photo Tracking¶
Developer documentation for the photo tracking feature.
Overview¶
The photo tracking system allows users to capture, import, organize, and compare transition photos. Photos are categorized by type and stored in the app's private internal storage with metadata in the Room database.
Photo Types¶
| Type | Constant | Description |
|---|---|---|
| Face | Photo.TYPE_FACE (0) |
Facial progress photos — great for tracking HRT facial changes |
| Body | Photo.TYPE_BODY (1) |
Full-body progress photos |
| Custom | Photo.TYPE_CUSTOM (2) |
User-defined areas (hands, legs, hair, etc.) |
| Audio | Photo.TYPE_AUDIO (3) |
Voice recordings (see Audio Tracking) |
CameraX Face-Detection Camera¶
OpenTransition includes a dedicated face-detection camera powered by CameraX and ML Kit Face Detection.
How It Works¶
- User taps the face photo capture button
- The
RecordAudioFragment/ face camera screen opens via CameraXPreview+ImageCapture - ML Kit's
FaceDetectorruns in real time on the camera preview stream - A bounding-box overlay guides the user to centre their face in the frame
- The shutter fires automatically when the face is well-centred, or the user taps manually
- The captured image is copied to internal storage and the
PhotoRoom entity is created
Key Files¶
mobile/src/main/java/com/shelbeely/opentransition/camera/— CameraX setup and ML Kit integrationmobile/src/main/res/layout/fragment_face_camera.xml— Camera preview with overlay
Dependencies¶
def camerax_version = "1.3.1"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
implementation 'com.google.mlkit:face-detection:16.1.6'
Importing Photos¶
Users can also import existing photos from their device gallery using Android's PickMultipleVisualMedia activity result API (no legacy READ_EXTERNAL_STORAGE permission needed on Android 13+).
MainActivityregisterspickMediaLauncherwithPickMultipleVisualMedia- Selected URIs are passed to
AssignPhotosFragmentvia SafeArgs AssignPhotosDomain.addPhotos()copies each image to internal storage and inserts aPhotoentity
Data Model¶
// Room entity
@Entity(tableName = "photos")
data class PhotoEntity(
@PrimaryKey val id: String = UUID.randomUUID().toString(),
val timestamp: Long,
val epochDay: Long,
val filename: String,
val type: Int
)
Photos are stored in mobile/src/main/java/com/shelbeely/opentransition/data/Photo.kt (Realm version retained for backwards compatibility with TransTracks import) and the Room entity in the database/ package.
Photo File Storage¶
Photos are copied to the app's private internal storage:
This directory is only accessible to the app and is excluded from Android backups by default. Use the Export feature to create a portable .ttbackup archive.
Implementation¶
See Data Layer for Photo model details and Architecture Overview for system design.
Related¶
- Audio Tracking — Voice recording feature
- Gallery — Browsing and comparing photos
- Import & Export — Backup and migration