This provides instructions for integrating and utilizing the Presage SmartSpectra SDK publicly hosted on Maven in your Android application to measure physiology metrics from a 30 second measurement using the mobile device's camera.
This app contained in this repo is an example of pulling and using the SmartSpectra SDK from Maven. It should run out of the box as long as your API key is provided.
Before you start, ensure your development environment includes:
- Android Studio Giraffe or later
- Minimum SDK level 26
To integrate the SmartSpectra SDK into your Android project, add the following dependency to your app's build.gradle
file:
dependencies {
implementation("com.presagetech:smartspectra:1.0.16-SNAPSHOT")
}
While the sdk library is in development process it may be necessary to add maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots")
to settings.gradle.kt
, like this:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots")
}
}
In your activity or fragment, initialize the SmartSpectraView
(The view consists of checkup button and result view):
import com.presagetech.smartspectra.SmartSpectraView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Setting up SmartSpectra Results/Views
smartSpectraView = findViewById(R.id.smart_spectra_view)
}
You need a valid API key to authenticate your requests:
//Required configuration
// Your api token from https://physiology.presagetech.com/
smartSpectraView.setApiKey("YOUR_API_KEY")
// Optional configurations
// Set measurement duration (valid range for spot time is between 20.0 and 120.0)
// Defaults to 30 if not specified otherwise
smartSpectraView.setSpotTime(30.0)
//whether to show fps in the previewDisplay
smartSpectraView.setShowFps(false)
// Whether to add a recording delay after start button is pressed
//Recording delay defaults to 3 if not provided
smartSpectraView.setRecordingDelay(3)
You can obtain an API key from PresageTech's developer portal (https://physiology.presagetech.com/)
To retrieve and use metrics, you can attach a metricsBufferObserver
to get the metrics to process. Please refer to MainActivity.kt for example usage and plotting of different metrics such as pulse rate, breathing rates etc.
import com.presage.physiology.proto.MetricsProto.MetricsBuffer
override fun onCreate(savedInstanceState: Bundle?) {
//...
//...
smartSpectraView.setMetricsBufferObserver { metricsBuffer ->
// Process meshPoints here
handleMetricsBuffer(metricsBuffer)
}
//...
//...
}
private fun handleMetricsBuffer(metrics: MetricsBuffer) {
// get the relevant metrics
val pulse = metrics.pulse
val breathing = metrics.breathing
// Plot the results
// Pulse plots
if (pulse.traceCount > 0) {
addChart(pulse.traceList.map { Entry(it.time, it.value) }, "Pulse Pleth", false)
}
// Breathing plots
if (breathing.upperTraceCount > 0) {
addChart(breathing.upperTraceList.map { Entry(it.time, it.value) }, "Breathing Pleth", false)
}
// TODO: See examples of plotting other metrics in MainActivity.kt
}
For facemesh points, you can attach a meshPointsObserver
to get the mesh points to process. To see an complete example of using scatter chart to visualize the mesh points, please refer to MainActivity.kt. Reference to the index of the mesh points and their corresponding face landmarks can be seen here
override fun onCreate(savedInstanceState: Bundle?) {
//...
//...
smartSpectraView.setMeshPointsObserver { meshPoints ->
// Process meshPoints here
handleMeshPoints(meshPoints)
}
//...
//...
}
private fun handleMeshPoints(meshPoints: List<Pair<Int, Int>>) {
Timber.d("Observed mesh points: ${meshPoints.size}")
// TODO: Update UI or handle the points as needed. See examples of plotting in MainActivity.kt
}
TIP If you need to use the types directly, the
MetricsBuffer
and corresponding classes are under thecom.presage.physiology.proto.MetricsProto
namespace. You can import it fromMetricsProto.MetricsBuffer
for easier usage:import com.presage.physiology.proto.MetricsProto.MetricsBuffer
MetricsBuffer
contains the following parent classes:
class MetricsBuffer {
var pulse: Pulse
var breathing: Breathing
var bloodPressure: BloodPressure
var face: Face
var metadata: Metadata
}
Measurement
Class: Represents a measurement with time and value:
class Measurement {
var time: Float
var value: Float
var stable: Boolean
}
MeasurementWithConfidence
Class: Includes confidence with the measurement:
class MeasurementWithConfidence {
var time: Float
var value: Float
var stable: Boolean
var confidence: Float
}
DetectionStatus
Class: Used for events like apnea or face detection (blinking/talking):
class DetectionStatus {
var time: Float
var detected: Boolean
var stable: Boolean
}
Pulse
Class: Contains pulse-related measurements, including rate, trace, and strict values:
class Pulse {
var rateList: List<MeasurementWithConfidence>
var traceList: List<Measurement>
var strict: Strict
}
Breathing
Class: Handles breathing-related data with upper and lower traces, amplitude, apnea status, and other metrics:
class Breathing {
var rateList: List<MeasurementWithConfidence>
var upperTraceList: List<Measurement>
var lowerTraceList: List<Measurement>
var amplitudeList: List<Measurement>
var apneaList: List<DetectionStatus>
var respiratoryLineLengthList: List<Measurement>
var inhaleExhaleRatioList: List<Measurement>
var strict: Strict
}
BloodPressure
Class: Handles blood pressure measurements:
Caution
Currently not available publicly, currently returned results are a duplicate of pulse pleth
class BloodPressure {
var phasicList: List<MeasurementWithConfidence>
}
Face
Class: Includes detection statuses for blinking and talking:
class Face {
var blinkingList: List<DetectionStatus>
var talkingList: List<DetectionStatus>
}
Metadata
Class: Includes metadata information:
class Metadata {
var id: String
var uploadTimestamp: String
var apiVersion: String
}
To serialize MetricsBuffer
into binary format:
try {
val data: ByteArray = metricsBuffer.toByteArray()
// Send `data` to your backend or save it
} catch (e: Exception) {
Timber.e("Failed to serialize metrics: ${e.message}")
}
To decode binary protobuf data into MetricsBuffer
:
try {
val decodedMetrics = MetricsBuffer.parseFrom(data)
// Use `decodedMetrics` as needed
} catch (e: Exception) {
Timber.e("Failed to decode metrics: ${e.message}")
}
You can obtain an API key from PresageTech's developer portal (https://physiology.presagetech.com/)
For additional support, contact support@presagetech.com or submit a github issue
- Currently, there are no known bugs. If you encounter an issue, please contact support or report it.