Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Wellness & Droid

Wellness & Droid

Slides of the talk I gave at Droidcon Italy together with Daniele Bonaldo

6923bdeb363961b064d2cdb6329982d6?s=128

Roberto Orgiu

April 04, 2022
Tweet

More Decks by Roberto Orgiu

Other Decks in Programming

Transcript

  1. WELLNESS & DROID Photo by Jeremy Thomas on Unsplash

  2. Daniele Bonaldo @danybony_ Roberto Orgiu @_ tiwiz

  3. SLEEP EXERCISE RECORD

  4. ACTIVITY RECOGNITION API EXERCISE

  5. Let’s get started •Track user •Compute distance •Steps measurement

  6. Getting last user’s location //Manifest.permission.ACCESS_FINE_LOCATION private val client = LocationServices.getFusedLocationProviderClient(

    activity ) client.lastLocation.addOnSuccessListener { location -> . .. }
  7. Getting updates on user’s location private val locationCallback = object

    : LocationCallback() { override fun onLocationResult(r: LocationResult) { // calculate here } }
  8. Getting updates on user’s location val locationRequest = LocationRequest .create().apply

    { priority = PRIORITY_HIGH_ACCURACY interval = 5000 }
  9. Getting updates on user’s location client.requestLocationUpdates( locationRequest, locationCallback, Looper.getMainLooper() )

  10. Compute distances SphericalUtil .computeDistanceBetween( lastLatLng, oldLatLng )

  11. class StepCounter( private val activity: AppCompatActivity ) : SensorEventListener Every

    step counts
  12. Every step counts private val sensorManager : SensorManager = activity.getSystemService(SENSOR_SERVICE)

    private val stepCounterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) private var initialSteps = -1
  13. Every step counts fun setupStepCounter() { if (stepCounterSensor != null)

    { sensorManager.registerListener(this, stepCounterSensor, SENSOR_DELAY_FASTEST) } } fun unloadStepCounter() { if (stepCounterSensor != null) { sensorManager.unregisterListener(this) } }
  14. Every step counts override fun onSensorChanged(event: SensorEvent) { event.values.firstOrNull() ?.

    toInt() ?. let { newSteps -> if (initialSteps == -1) { initialSteps = newSteps } currentSteps = newSteps - initialSteps } } override fun onAccuracyChanged( sensor: Sensor, accuracy: Int ) = Unit
  15. SLEEP EXERCISE RECORD

  16. SLEEP SLEEP RECOGNITION API

  17. Sleep classify event Sleep segment event

  18. Sleep segment event •Start timestamp •End timestamp •Duration •Status •Successful

    •Not detected •Missing data
  19. Sleep classify event •Confidence •Light level •Motion level •Timestamp

  20. M T W T F S S

  21. M T W T F S S

  22. Setup Requirements •Android API Level > v29 •Android Build Tools

    > v21 •Google Play Services Dependency •com.google.android.gms:play-services-location:21.0.0
  23. Receiver Android Manifest <receiver android:name=".receiver.SleepReceiver" android:enabled="true" android:exported="true" />

  24. Receiver Android Manifest <receiver android:name=".receiver.SleepReceiver" android:enabled="true" android:exported="true" /> SleepReceiver :

    BroadcastReceiver() override fun onReceive(context: Context, intent: Intent) { if (SleepSegmentEvent.hasEvents(intent)) { .. . } else if (SleepClassifyEvent.hasEvents(intent)) { .. . } }
  25. Permissions Android Manifest <uses-permission android:name=“android.permission.ACTIVITY_RECOGNITION" />

  26. Permissions Android Manifest <uses-permission android:name=“android.permission.ACTIVITY_RECOGNITION" / > MainActivity ContextCompat.checkSelfPermission( context,

    permission.ACTIVITY_RECOGNITION )_
  27. Permissions Android Manifest <uses-permission android:name=“android.permission.ACTIVITY_RECOGNITION" / > MainActivity ContextCompat.checkSelfPermission(context,permission.ACTIVITY_RECOGNITION)_ val

    requestPermissionLauncher: ActivityResultLauncher<String> = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (!isGranted) { … } else { // ready } } requestPermissionLauncher.launch(permission.ACTIVITY_RECOGNITION)
  28. Permissions Android Manifest <uses-permission android:name=“android.permission.ACTIVITY_RECOGNITION" / > MainActivity ContextCompat.checkSelfPermission(context,permission.ACTIVITY_RECOGNITION)_ val

    requestPermissionLauncher: ActivityResultLauncher<String> = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (!isGranted) { requestActivityRecognitionPermission() } else { // ready } } requestPermissionLauncher.launch(permission.ACTIVITY_RECOGNITION) private fun requestActivityRecognitionPermission() { val intent = Intent().apply { action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS data = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null) flags = Intent.FLAG_ACTIVITY_NEW_TASK } startActivity(intent) }
  29. Subscribe to sleep updates MainActivity ActivityRecognition.getClient(context) .requestSleepSegmentUpdates( pendingIntent, SleepSegmentRequest.getDefaultSleepSegmentRequest() )

  30. Confidence Motion Light Segments

  31. SLEEP EXERCISE RECORD

  32. GOOGLE FIT API RECORD

  33. Choose options val fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ) .addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)

    .build()
  34. Request permissions val account = GoogleSignIn.getAccountForExtension( activity, fitnessOptions) if (!GoogleSignIn.hasPermissions(account,

    fitnessOptions)) { GoogleSignIn.requestPermissions( activity, PERMISSIONS_REQUEST_CODE, account, fitnessOptions) } else { recordToGoogleFit() }
  35. Choose options override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)

    { super.onActivityResult(requestCode, resultCode, data) when (resultCode) { Activity.RESULT_OK - > when (requestCode) { PERMISSIONS_REQUEST_CODE -> recordToGoogleFit() else -> { . .. } } else - > { ... } } }
  36. Create a session val session = Session.Builder() .setName("Today's Run") .setIdentifier("Unique_Identifier_Here")

    .setDescription("Long run around home") .setActivity(FitnessActivities.RUNNING) .setStartTime(startTime, TimeUnit.MILLISECONDS) .setEndTime(endTime, TimeUnit.MILLISECONDS) .build()
  37. Create a request val insertRequest = SessionInsertRequest.Builder() .setSession(session) .build()

  38. Insert request Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions) ) .insertSession(insertRequest) .addOnSuccessListener { ...

    } .addOnFailureListener { e -> ... }
  39. Q&A Photo by Simone Secci on Unsplash