Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Wellness & Droid
Search
Roberto Orgiu
April 04, 2022
Programming
0
110
Wellness & Droid
Slides of the talk I gave at Droidcon Italy together with Daniele Bonaldo
Roberto Orgiu
April 04, 2022
Tweet
Share
More Decks by Roberto Orgiu
See All by Roberto Orgiu
Behind the curtains
tiwiz
0
58
The Importance of Being Tested
tiwiz
0
410
An Android Dev start to Kotlin MPP
tiwiz
0
170
Fantastic API and where to find them
tiwiz
0
69
Flipping the Koin @ GDG Dev Party
tiwiz
1
65
Flipping the Koin
tiwiz
2
150
Trip into the async world @ NYC Kotlin Meetup
tiwiz
0
110
Trip into the async world
tiwiz
1
130
GraphQL IRL (Android Makers)
tiwiz
0
150
Other Decks in Programming
See All in Programming
20 years of Symfony, what's next?
fabpot
2
310
ID管理機能開発の裏側 高速にSaaS連携を実現したチームのAI活用編
atzzcokek
0
190
[堅牢.py #1] テストを書かない研究者に送る、最初にテストを書く実験コード入門 / Let's start your ML project by writing tests
shunk031
11
6.9k
Querying Design System デザインシステムの意思決定を支える構造検索
ikumatadokoro
1
1.2k
宅宅自以為的浪漫:跟 AI 一起為自己辦的研討會寫一個售票系統
eddie
0
470
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
210
30分でDoctrineの仕組みと使い方を完全にマスターする / phpconkagawa 2025 Doctrine
ttskch
3
730
令和最新版Android Studioで化石デバイス向けアプリを作る
arkw
0
200
AWS CDKの推しポイントN選
akihisaikeda
1
240
AIコーディングエージェント(Manus)
kondai24
0
130
AIエージェントを活かすPM術 AI駆動開発の現場から
gyuta
0
230
tparseでgo testの出力を見やすくする
utgwkk
1
130
Featured
See All Featured
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
The Language of Interfaces
destraynor
162
25k
Site-Speed That Sticks
csswizardry
13
990
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.1k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.7k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.2k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
How STYLIGHT went responsive
nonsquared
100
5.9k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.4k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.1k
Code Review Best Practice
trishagee
73
19k
Transcript
WELLNESS & DROID Photo by Jeremy Thomas on Unsplash
Daniele Bonaldo @danybony_ Roberto Orgiu @_ tiwiz
SLEEP EXERCISE RECORD
ACTIVITY RECOGNITION API EXERCISE
Let’s get started •Track user •Compute distance •Steps measurement
Getting last user’s location //Manifest.permission.ACCESS_FINE_LOCATION private val client = LocationServices.getFusedLocationProviderClient(
activity ) client.lastLocation.addOnSuccessListener { location -> . .. }
Getting updates on user’s location private val locationCallback = object
: LocationCallback() { override fun onLocationResult(r: LocationResult) { // calculate here } }
Getting updates on user’s location val locationRequest = LocationRequest .create().apply
{ priority = PRIORITY_HIGH_ACCURACY interval = 5000 }
Getting updates on user’s location client.requestLocationUpdates( locationRequest, locationCallback, Looper.getMainLooper() )
Compute distances SphericalUtil .computeDistanceBetween( lastLatLng, oldLatLng )
class StepCounter( private val activity: AppCompatActivity ) : SensorEventListener Every
step counts
Every step counts private val sensorManager : SensorManager = activity.getSystemService(SENSOR_SERVICE)
private val stepCounterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) private var initialSteps = -1
Every step counts fun setupStepCounter() { if (stepCounterSensor != null)
{ sensorManager.registerListener(this, stepCounterSensor, SENSOR_DELAY_FASTEST) } } fun unloadStepCounter() { if (stepCounterSensor != null) { sensorManager.unregisterListener(this) } }
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
SLEEP EXERCISE RECORD
SLEEP SLEEP RECOGNITION API
Sleep classify event Sleep segment event
Sleep segment event •Start timestamp •End timestamp •Duration •Status •Successful
•Not detected •Missing data
Sleep classify event •Confidence •Light level •Motion level •Timestamp
M T W T F S S
M T W T F S S
Setup Requirements •Android API Level > v29 •Android Build Tools
> v21 •Google Play Services Dependency •com.google.android.gms:play-services-location:21.0.0
Receiver Android Manifest <receiver android:name=".receiver.SleepReceiver" android:enabled="true" android:exported="true" />
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)) { .. . } }
Permissions Android Manifest <uses-permission android:name=“android.permission.ACTIVITY_RECOGNITION" />
Permissions Android Manifest <uses-permission android:name=“android.permission.ACTIVITY_RECOGNITION" / > MainActivity ContextCompat.checkSelfPermission( context,
permission.ACTIVITY_RECOGNITION )_
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)
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) }
Subscribe to sleep updates MainActivity ActivityRecognition.getClient(context) .requestSleepSegmentUpdates( pendingIntent, SleepSegmentRequest.getDefaultSleepSegmentRequest() )
Confidence Motion Light Segments
SLEEP EXERCISE RECORD
GOOGLE FIT API RECORD
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()
Request permissions val account = GoogleSignIn.getAccountForExtension( activity, fitnessOptions) if (!GoogleSignIn.hasPermissions(account,
fitnessOptions)) { GoogleSignIn.requestPermissions( activity, PERMISSIONS_REQUEST_CODE, account, fitnessOptions) } else { recordToGoogleFit() }
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 - > { ... } } }
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()
Create a request val insertRequest = SessionInsertRequest.Builder() .setSession(session) .build()
Insert request Fitness.getSessionsClient(this, GoogleSignIn.getAccountForExtension(this, fitnessOptions) ) .insertSession(insertRequest) .addOnSuccessListener { ...
} .addOnFailureListener { e -> ... }
Q&A Photo by Simone Secci on Unsplash