SlideShare une entreprise Scribd logo
1  sur  65
Télécharger pour lire hors ligne
Google Fit, Wear & Xamarin
Peter Friese @peterfriese
Matt Sullivan @mjohnsullivan
Code Lab
Food for Thought
Are Fitness apps just for
runners, cyclists, athletes?
Or for those on a mission to get
fit and stay healthy?
Can we add elements of fitness
to everyday apps?
http://handy-games.com/games/kitty-my-fitness-cat/
Positive impact on physical and
emotional wellbeing
==
positive impact on user
experience and happiness
Android Wear
Create a Wear app module
Design the watch face UI
Extend WatchFaceService.Engine
Create a companion app
1
2
3
4
Watch Face Architecture
Wearable App
CanvasWatchFaceService
Engine
WearableConfigActivity
WearableListenerService
Mobile App
MobileConfigActivity
Design for square
and round
Interactive and
Ambient Modes
Gestures
CanvasWatchFaceService.Engine
UI Drawing
Manually draw onto
a Canvas Object
Ambient Mode Changes
Reduced color space
Burn protection
Redraw Intervals
Once a minute in
Ambient – OnTimeTick()
Custom for interactive
– use a System Timer
TimeZone Changes
Use a BroadcastReceiver
Interactive Watch Faces
.SetAcceptsTapEvents() in Builder
Override OnTapCommand()
Drawing the watch face
Background
Hour Ticks
Step Count
Minutes Hand
Seconds Hand
Hours Hand
backgroundScaledBitmap =
Bitmap.CreateScaledBitmap(backgroundBitmap,

width, height, true);

canvas.DrawBitmap(backgroundScaledBitmap, 0, 0, null);



Drawing the Watch Face - Background
var innerTickRadius = centerX - 10;

var outerTickRadius = centerX;

for (var tickIndex = 0; tickIndex < 12; tickIndex++)

{

	 var tickRot = (float)(tickIndex * Math.PI * 2 / 12);

	 var innerX = (float)Math.Sin(tickRot) * innerTickRadius;

	 var innerY = (float)-Math.Cos(tickRot) * innerTickRadius;

	 var outerX = (float)Math.Sin(tickRot) * outerTickRadius;

	 var outerY = (float)-Math.Cos(tickRot) * outerTickRadius;


	 canvas.DrawLine(centerX + innerX, centerY + innerY,

	 centerX + outerX, centerY + outerY, tickPaint);

}



Drawing the Watch Face - Ticks
var width = bounds.Width();

var height = bounds.Height();



var steps = stepCount.ToString();

var stepsWidth = stepcountPaint.MeasureText(steps);



var x = width - stepsWidth - stepCountOffset;

var y = (height + stepCountTextSize) / 2.0f;



canvas.DrawText(steps, x, y, stepcountPaint);

Drawing the Watch Face - Step Count
Ambient mode
Reduce color depth
Reduce number of non-black pixels
Use color for < 5% pixels
Watch face updates
once a minute -
don’t show seconds
Save power
Interactive Ambient
public override void OnDraw(Canvas canvas, Rect bounds)

{

	 DrawFace(canvas, bounds);

	 DrawHands(canvas, bounds);

}



void DrawHands(Canvas canvas, Rect bounds)

{

	 if (!IsInAmbientMode) {

	 	 canvas.DrawLine(centerX, centerY,
centerX + secX, centerY + secY, secondPaint);

	 }



	 canvas.DrawLine(centerX, centerY,
centerX + minX, centerY + minY, minutePaint);

}
Ambient Mode
public override void OnDraw(Canvas canvas, Rect bounds)

{

	 DrawFace(canvas, bounds);

	 DrawHands(canvas, bounds);

}



void DrawHands(Canvas canvas, Rect bounds)

{

	 if (!IsInAmbientMode) {

	 	 canvas.DrawLine(centerX, centerY,
centerX + secX, centerY + secY, secondPaint);

	 }



	 canvas.DrawLine(centerX, centerY,
centerX + minX, centerY + minY, minutePaint);

}
Ambient Mode
No seconds hand
in ambient mode
void UpdateTimer()

{

	 if (timerSeconds == null) {

	 	 timerSeconds = new System.Threading.Timer(

	 	 	 state => {

	 	 	 	 Invalidate();

	 	 	 },

	 	 	 null, dueTime, period

	 }

	 else {

	 	 if (IsVisible && !IsInAmbientMode) {

	 	 	 timerSeconds.Change(0, InteractiveUpdateRateMs);

	 	 }

	 	 else {

	 	 	 timerSeconds.Change(System.Threading.Timeout.Infinite, 0);

	 	 }

	 }

}
Ambient Mode / 2
void UpdateTimer()

{

	 if (timerSeconds == null) {

	 	 timerSeconds = new System.Threading.Timer(

	 	 	 state => {

	 	 	 	 Invalidate();

	 	 	 },

	 	 	 null, dueTime, period

	 }

	 else {

	 	 if (IsVisible && !IsInAmbientMode) {

	 	 	 timerSeconds.Change(0, InteractiveUpdateRateMs);

	 	 }

	 	 else {

	 	 	 timerSeconds.Change(System.Threading.Timeout.Infinite, 0);

	 	 }

	 }

}
Ambient Mode / 2
Redraw every second when
in interactive mode
void UpdateTimer()

{

	 if (timerSeconds == null) {

	 	 timerSeconds = new System.Threading.Timer(

	 	 	 state => {

	 	 	 	 Invalidate();

	 	 	 },

	 	 	 null, dueTime, period

	 }

	 else {

	 	 if (IsVisible && !IsInAmbientMode) {

	 	 	 timerSeconds.Change(0, InteractiveUpdateRateMs);

	 	 }

	 	 else {

	 	 	 timerSeconds.Change(System.Threading.Timeout.Infinite, 0);

	 	 }

	 }

}
Ambient Mode / 2
Turn timer
on in interactive mode
off in ambient mode
Configuration Activities
WEARABLE_CONFIGURATION on Wear
COMPANION_CONFIGURATION on Phone
DataLayer API
Listen for Data Item Events
Write DataItems to URI Paths
void SaveStepCountStatus(GoogleApiClient googleApiClient, bool stepCountOn)
{
var putDataMapRequest = PutDataMapRequest.Create("/xfit_watchface");
putDataMapRequest.DataMap.PutBoolean("stepcount", stepCountOn);
var putDataRequest = putDataMapRequest.AsPutDataRequest();
putDataRequest.SetUrgent();
WearableClass.DataApi.PutDataItem(googleApiClient, putDataRequest);
}
Syncing configuration /1
void SaveStepCountStatus(GoogleApiClient googleApiClient, bool stepCountOn)
{
var putDataMapRequest = PutDataMapRequest.Create("/xfit_watchface");
putDataMapRequest.DataMap.PutBoolean("stepcount", stepCountOn);
var putDataRequest = putDataMapRequest.AsPutDataRequest();
putDataRequest.SetUrgent();
WearableClass.DataApi.PutDataItem(googleApiClient, putDataRequest);
}
Syncing configuration /1
URI Path
Data Item Key
Sync now
void OnDataChanged(DataEventBuffer dataEvents)
{
foreach (var dataEvent in dataEvents)
{
var dataItem = dataEvent.DataItem;
if (dataItem.Uri.Path == "/xfit_watchface")
{
var dataMap = DataMapItem.FromDataItem(dataItem).DataMap;
displayStepCount = dataMap.GetBoolean(“stepcount”);
Invalidate(); // force redraw
}
}
}
Syncing configuration /2
void OnDataChanged(DataEventBuffer dataEvents)
{
foreach (var dataEvent in dataEvents)
{
var dataItem = dataEvent.DataItem;
if (dataItem.Uri.Path == "/xfit_watchface")
{
var dataMap = DataMapItem.FromDataItem(dataItem).DataMap;
displayStepCount = dataMap.GetBoolean(“stepcount”);
Invalidate(); // force redraw
}
}
}
Implements IDataApiDataListener
Syncing configuration /2
URI Path
Data Item Key
Watch face drawing code
GoogleAPIClient code
Configuration code
Reading the step count code
1
2
3
4
Clean Code
Partial Classes
XFitWatchfaceService
XFitWatchFaceEngine
(Drawing Code)
XFitWatchFaceEngine
(Config Code)
XFitWatchFaceEngine
(Google API Client Code)
XFitWatchFaceEngine
(Step Count Code)
XFitWatchFaceEngine
Partial Classes
XFitWatchfaceService
XFitWatchFaceEngine
(Drawing Code)
XFitWatchFaceEngine
(Config Code)
XFitWatchFaceEngine
(Google API Client Code)
XFitWatchFaceEngine
(Step Count Code)
XFitWatchFaceEngine
[Service(Label = "XFit Watchface 4",
Permission = "android.permission.BIND_WALLPAPER")]

[IntentFilter(new[] { "android.service.wallpaper.WallpaperService" },
Categories = new[]
{ "com.google.android.wearable.watchface.category.WATCH_FACE" })]

public partial class XFitWatchfaceService: CanvasWatchFaceService

{



	 public override WallpaperService.Engine OnCreateEngine()

	 {

	 	 return new XFitWatchfaceEngine(this);

	 }



	 partial class XFitWatchfaceEngine : Engine

	 {
// drawing code

	 }
}
XFitWatchfaceService.cs (Drawing Code)
Partial Classes
XFitWatchfaceService
XFitWatchFaceEngine
(Drawing Code)
XFitWatchFaceEngine
(Config Code)
XFitWatchFaceEngine
(Google API Client Code)
XFitWatchFaceEngine
(Step Count Code)
XFitWatchFaceEngine
[MetaData(
"com.google.android.wearable.watchface.wearableConfigurationAction",
Value = "XFitWatchface.CONFIG")]

[MetaData(
"com.google.android.wearable.watchface.companionConfigurationAction",
Value = "XFitWatchface.CONFIG")]
public partial class XFitWatchfaceService : CanvasWatchFaceService

{



	 partial class XFitWatchfaceEngine : Engine, IDataApiDataListener

	 {

	 	 void ConnectWatchfaceConfigUpdates()
	 	 {

	 	 }

	 }

}

XFitWatchfaceServiceConfig.cs (Config Code)
Partial Classes
XFitWatchfaceService
XFitWatchFaceEngine
(Drawing Code)
XFitWatchFaceEngine
(Config Code)
XFitWatchFaceEngine
(Google API Client Code)
XFitWatchFaceEngine
(Step Count Code)
XFitWatchFaceEngine
public partial class XFitWatchfaceService : CanvasWatchFaceService

{



	 partial class XFitWatchfaceEngine : Engine

	 {

	 	 GoogleApiClient googleApiClient;



	 	 void ConnectGoogleApiClient()

	 	 {

	 	 	 googleApiClient = new GoogleApiClient.Builder(owner)
	 	 	 	 .AddApi(FitnessClass.HISTORY_API)

	 	 	 	 .AddApi(FitnessClass.RECORDING_API)

	 	 	 	 .AddApi(WearableClass.API)
	 	 	 	 .Build();
	 	 	 googleApiClient.Connect();

	 	 }

	 }

}
XFitWatchfaceServiceGoogleApiClient.cs (Google API Client)
Google Fit
Activity Read/Write
Body Read/Write
Location Read/Write
Nutrition Read/Write
Sleep Duration & Type
Calories Consumed, Macronutrients
Height, Weight, BMI, Body Fat %
Heart Rate
Distance Traveled
Steps
Calories Burned
Activity Segments (walking, running, biking)
Gym Activities
ACTIVITY
NUTRITION
BODY
SLEEP
SENSORS API
RECORDING API
HISTORY API
SESSIONS API
SENSORS API
Find all sensors, both on and off-device
FindDataSources (GoogleApiClient c, DataSourcesRequest r)
Register for sensor data
Add (GoogleApiClient c, SensorRequest r, IOnDataPointListener l);
Unregister for sensor data
Remove (GoogleApiClient c, IOnDataPointListener l);
RECORDING API
Stop recording data types/sources
Unsubscribe (GoogleApiClient c, DataType t)
Unsubscribe (GoogleApiClient c, DataSource s)
What data is being recorded
ListSubscriptions (GoogleApiClient c)
Record from data types/sources
Subscribe (GoogleApiClient c, DataType t)
Subscribe (GoogleApiClient c, DataSource s)
HISTORY API
Manually add data
InsertData (GoogleApiClient c, DataSet d)
Remove data
DeleteData (GoogleApiClient c, DeleteDataRequest r)
Retrieve data
void ReadData (GoogleApiClient c, DataReadRequest r)
SESSIONS API
Start recording a live session
void StartSession(GoogleApiClient client, Session session);
Stop recording a live session
void StopSession (GoogleApiClient client, String identifier);
Insert a session
void InsertSession (GoogleApiClient client, SessionInsertRequest request)
curl 
-H "Content-Type: application/json" 
-H "Authorization: Bearer $ACCESS_TOKEN" 
https://www.googleapis.com/fitness/v1/users/me/dataSources/
derived:com.google.step_count.delta:...:estimated_steps/
datasets/1438701040000000000-143930584000000000
REST API
Reading Steps
Create a GoogleApiClient
Ensure device is recording steps
Build an aggregated query
Read and extract the data
1
2
3
4
void BuildApiClient ()
{
googleApiClient = new GoogleApiClient.Builder (this)
.AddApi (FitnessClass.HISTORY_API)
.AddApi (FitnessClass.RECORDING_API)
.AddScope (FitnessClass.ScopeActivityReadWrite)
.EnableAutoManage (this, AuthClientId,
result => {
// Unresolvable error, handle or fail silently
})
.Build ();
SubscribeToSteps ();
ReadSteps ();
}
Read before connection
established
Auto manage
connection
Build API Client
void SubscribeToSteps ()
{
FitnessClass.RecordingApi.Subscribe (googleApiClient,
TypeStepCountDelta)
.SetResultCallback( (IResult result) => {
if (!result.Status.IsSuccess)
{
// Error subscribing, handle
}
});
}
Subscribing
// Read step count deltas from the History API
DataReadRequest DailyStepsForWeek()
{
long midnight = TimeUtility.MidnightLocalPosix ();
long midnightWeekAgo = TimeUtility.DaysAgoPosix (midnight, 7);
return new DataReadRequest.Builder ()
.Aggregate (DataType.TypeStepCountDelta,
DataType.AggregateStepCountDelta)
.BucketByTime (1, TimeUnit.Days)
.SetTimeRange (midnightWeekAgo, midnight,
TimeUnit.Milliseconds)
.Build();
}
Data
Aggregation
Data Read Request
// Reads and extracts step data
void ReadDailySteps ()
{
DataReadRequest readRequest = RequestBuilder.DailyStepsForWeek ();
FitnessClass.HistoryApi.ReadData (googleApiClient, readRequest)
.SetResultCallback ( (IResult result) => {
IList<Bucket> buckets = ((DataReadResult)result).Buckets;
foreach (var bucket in buckets)
{
var stepCount = bucket.DataSets.Sum(dataSet =>
dataSet.DataPoints.Sum (dp =>
dp.DataType.Fields.Sum (f =>
dp.GetValue (f).AsInt())));
Log.Info (Tag, $"Step Count: {stepCount}");
}
});
}
Reading
Data
Extracting
Data
Read Daily Steps
Writing Data
// Writing data
googleApiClient = new GoogleApiClient.Builder(context)
.AddApi(...)
.AddConnectionCallbacks(
connectionHint => { // Connected! },
cause => { // Suspended }
).Build();
Writes require
an established
connection
Writing Data
Reading Today’s
Steps
Create a GoogleApiClient
Ensure device is recording steps
Build an aggregated query
Read and extract the data
1
2
3
3
Create a GoogleApiClient
Ensure device is recording steps
Read and extract the data
1
2
2
// All in one reading steps
void AllInOne()
{
var client = new GoogleApiClient.Builder (this)
.AddApi (FitnessClass.HISTORY_API)
.UseDefaultAccount ()
.Build ();
client.Connect ();
FitnessClass.HistoryApi.ReadDailyTotal (client, TypeStepCountDelta)
.SetResultCallback ( (IResult result) => {
DataSet ds = ((DailyTotalResult) result).Total;
int stepCount = ds.DataPoints.Sum (
dp => dp.DataType.Fields.Sum (
f => dp.GetValue (f).AsInt()));
});
}
Default
Account Read Daily Total
Read Today’s Steps
Code Lab
Thank You!
https://developers.google.com/fit/
https://developer.android.com/wear/
http://developer.android.com/training/wearables/watch-faces/

Contenu connexe

Tendances

Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...
Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...
Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...paez2012
 
мэдрэл тест
мэдрэл тестмэдрэл тест
мэдрэл тестnayna-1
 
Αναπαραγωγή στον άνθρωπο
Αναπαραγωγή στον άνθρωποΑναπαραγωγή στον άνθρωπο
Αναπαραγωγή στον άνθρωποDespina Setaki
 
Home care nurse role lekts 2
Home care nurse role lekts 2Home care nurse role lekts 2
Home care nurse role lekts 2dondooubuns
 
Сэтгэн бодох шийдвэр гаргах арга зүй-тест
Сэтгэн бодох шийдвэр гаргах арга зүй-тестСэтгэн бодох шийдвэр гаргах арга зүй-тест
Сэтгэн бодох шийдвэр гаргах арга зүй-тестsaruul tungalag
 
Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...
Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...
Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...Ankhbileg Luvsan
 
тема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світі
тема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світітема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світі
тема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світіcit-cit
 
жилийн тайлан 2017-дздтг
жилийн тайлан 2017-дздтгжилийн тайлан 2017-дздтг
жилийн тайлан 2017-дздтгadmiral_mgl
 
жирэмслэлт ба эсэн мэнд амаржихуй 2014
жирэмслэлт ба эсэн мэнд амаржихуй 2014жирэмслэлт ба эсэн мэнд амаржихуй 2014
жирэмслэлт ба эсэн мэнд амаржихуй 2014Yanjaabzd
 
түнхний төрөлхийн мултрал
түнхний төрөлхийн мултралтүнхний төрөлхийн мултрал
түнхний төрөлхийн мултралZoloo Ganbat
 
Лекція Захворювання органів дихання.pptx
Лекція  Захворювання органів дихання.pptxЛекція  Захворювання органів дихання.pptx
Лекція Захворювання органів дихання.pptxTetianaitova
 
таниулсан зөвшөөрөл баримтын судалгаа
таниулсан зөвшөөрөл  баримтын судалгаатаниулсан зөвшөөрөл  баримтын судалгаа
таниулсан зөвшөөрөл баримтын судалгааnaranbatn
 
цанх(хэвлийгээр өвдөх хам шинж) өвчин
цанх(хэвлийгээр өвдөх хам шинж) өвчинцанх(хэвлийгээр өвдөх хам шинж) өвчин
цанх(хэвлийгээр өвдөх хам шинж) өвчинTugsuu Tugsuu
 
Eh barih emegteaichuud sudlal
Eh barih emegteaichuud sudlalEh barih emegteaichuud sudlal
Eh barih emegteaichuud sudlalGantulga Nyamdorj
 
ΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdf
ΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdfΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdf
ΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdfΜαυρουδης Μακης
 
мясная, шерстная, смушковая и шубная продуктивность
мясная, шерстная, смушковая и шубная продуктивностьмясная, шерстная, смушковая и шубная продуктивность
мясная, шерстная, смушковая и шубная продуктивностьЕвгений Баркарь
 

Tendances (20)

Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...
Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...
Project Β΄ Λυκείου 2015-2016, Β3, Τα ναρκωτικά ως κοινωνική μάστιγα και η επί...
 
мэдрэл тест
мэдрэл тестмэдрэл тест
мэдрэл тест
 
10 илтгэцүүр
10 илтгэцүүр10 илтгэцүүр
10 илтгэцүүр
 
Αναπαραγωγή στον άνθρωπο
Αναπαραγωγή στον άνθρωποΑναπαραγωγή στον άνθρωπο
Αναπαραγωγή στον άνθρωπο
 
Home care nurse role lekts 2
Home care nurse role lekts 2Home care nurse role lekts 2
Home care nurse role lekts 2
 
Сэтгэн бодох шийдвэр гаргах арга зүй-тест
Сэтгэн бодох шийдвэр гаргах арга зүй-тестСэтгэн бодох шийдвэр гаргах арга зүй-тест
Сэтгэн бодох шийдвэр гаргах арга зүй-тест
 
Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...
Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...
Эмийн талаар төрөөс баримтлах бодлогыг дархан уул аймагт хэрэгжүүлэх боломжыг...
 
тема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світі
тема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світітема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світі
тема 2. становлення, розвиток і сучасний стан переробки мяса в україні та світі
 
жилийн тайлан 2017-дздтг
жилийн тайлан 2017-дздтгжилийн тайлан 2017-дздтг
жилийн тайлан 2017-дздтг
 
жирэмслэлт ба эсэн мэнд амаржихуй 2014
жирэмслэлт ба эсэн мэнд амаржихуй 2014жирэмслэлт ба эсэн мэнд амаржихуй 2014
жирэмслэлт ба эсэн мэнд амаржихуй 2014
 
түнхний төрөлхийн мултрал
түнхний төрөлхийн мултралтүнхний төрөлхийн мултрал
түнхний төрөлхийн мултрал
 
2 lesson 2012 a
2 lesson 2012 a2 lesson 2012 a
2 lesson 2012 a
 
Лекція Захворювання органів дихання.pptx
Лекція  Захворювання органів дихання.pptxЛекція  Захворювання органів дихання.pptx
Лекція Захворювання органів дихання.pptx
 
таниулсан зөвшөөрөл баримтын судалгаа
таниулсан зөвшөөрөл  баримтын судалгаатаниулсан зөвшөөрөл  баримтын судалгаа
таниулсан зөвшөөрөл баримтын судалгаа
 
Presentation2
Presentation2Presentation2
Presentation2
 
ΣΜΝ-ΕΡΩΤΗΜΑΤΟΛΟΓΙΟ
ΣΜΝ-ΕΡΩΤΗΜΑΤΟΛΟΓΙΟΣΜΝ-ΕΡΩΤΗΜΑΤΟΛΟΓΙΟ
ΣΜΝ-ΕΡΩΤΗΜΑΤΟΛΟΓΙΟ
 
цанх(хэвлийгээр өвдөх хам шинж) өвчин
цанх(хэвлийгээр өвдөх хам шинж) өвчинцанх(хэвлийгээр өвдөх хам шинж) өвчин
цанх(хэвлийгээр өвдөх хам шинж) өвчин
 
Eh barih emegteaichuud sudlal
Eh barih emegteaichuud sudlalEh barih emegteaichuud sudlal
Eh barih emegteaichuud sudlal
 
ΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdf
ΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdfΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdf
ΕΠΑΓΩΓΗ ΕΡΩΤΗΣΕΙΣ ΜΕ ΑΠΑΝΤΗΣΕΙΣ 2023.pdf
 
мясная, шерстная, смушковая и шубная продуктивность
мясная, шерстная, смушковая и шубная продуктивностьмясная, шерстная, смушковая и шубная продуктивность
мясная, шерстная, смушковая и шубная продуктивность
 

Similaire à Google Fit, Android Wear & Xamarin

Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Alfredo Morresi
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Korhan Bircan
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear EssentialsNilhcem
 
Android Wear, a developer's perspective
Android Wear, a developer's perspectiveAndroid Wear, a developer's perspective
Android Wear, a developer's perspectiveSebastian Vieira
 
Kotlin Mullets
Kotlin MulletsKotlin Mullets
Kotlin MulletsJames Ward
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonfNataliya Patsovska
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Mahmoud Hamed Mahmoud
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in AndroidRobert Cooper
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentanistar sung
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
Developing AIR for Android with Flash Professional CS5
Developing AIR for Android with Flash Professional CS5Developing AIR for Android with Flash Professional CS5
Developing AIR for Android with Flash Professional CS5Chris Griffith
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...DroidConTLV
 
Developing AIR for Android with Flash Professional
Developing AIR for Android with Flash ProfessionalDeveloping AIR for Android with Flash Professional
Developing AIR for Android with Flash ProfessionalChris Griffith
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developersPavel Lahoda
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon Berlin
 

Similaire à Google Fit, Android Wear & Xamarin (20)

Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear Essentials
 
Android Wear, a developer's perspective
Android Wear, a developer's perspectiveAndroid Wear, a developer's perspective
Android Wear, a developer's perspective
 
Kotlin Mullets
Kotlin MulletsKotlin Mullets
Kotlin Mullets
 
Android 3
Android 3Android 3
Android 3
 
Android Oreo
Android OreoAndroid Oreo
Android Oreo
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
What's New in Android
What's New in AndroidWhat's New in Android
What's New in Android
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app development
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Developing AIR for Android with Flash Professional CS5
Developing AIR for Android with Flash Professional CS5Developing AIR for Android with Flash Professional CS5
Developing AIR for Android with Flash Professional CS5
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
 
Backendless apps
Backendless appsBackendless apps
Backendless apps
 
Developing AIR for Android with Flash Professional
Developing AIR for Android with Flash ProfessionalDeveloping AIR for Android with Flash Professional
Developing AIR for Android with Flash Professional
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developers
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
 
Custom components
Custom componentsCustom components
Custom components
 

Plus de Peter Friese

Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsPeter Friese
 
Firebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopFirebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopPeter Friese
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsPeter Friese
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesFirebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesPeter Friese
 
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift LeedsPeter Friese
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in SwiftPeter Friese
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple DevelopersPeter Friese
 
Building Apps with SwiftUI and Firebase
Building Apps with SwiftUI and FirebaseBuilding Apps with SwiftUI and Firebase
Building Apps with SwiftUI and FirebasePeter Friese
 
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebaseRapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebasePeter Friese
 
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebaseRapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebasePeter Friese
 
6 Things You Didn't Know About Firebase Auth
6 Things You Didn't Know About Firebase Auth6 Things You Didn't Know About Firebase Auth
6 Things You Didn't Know About Firebase AuthPeter Friese
 
Five Things You Didn't Know About Firebase Auth
Five Things You Didn't Know About Firebase AuthFive Things You Didn't Know About Firebase Auth
Five Things You Didn't Know About Firebase AuthPeter Friese
 
Building High-Quality Apps for Google Assistant
Building High-Quality Apps for Google AssistantBuilding High-Quality Apps for Google Assistant
Building High-Quality Apps for Google AssistantPeter Friese
 
Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google Peter Friese
 
Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on GoogleBuilding Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on GooglePeter Friese
 
What's new in Android Wear 2.0
What's new in Android Wear 2.0What's new in Android Wear 2.0
What's new in Android Wear 2.0Peter Friese
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android WearPeter Friese
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services RockPeter Friese
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android WearPeter Friese
 
Google+ for Mobile Apps on iOS and Android
Google+ for Mobile Apps on iOS and AndroidGoogle+ for Mobile Apps on iOS and Android
Google+ for Mobile Apps on iOS and AndroidPeter Friese
 

Plus de Peter Friese (20)

Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI Components
 
Firebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopFirebase & SwiftUI Workshop
Firebase & SwiftUI Workshop
 
Building Reusable SwiftUI Components
Building Reusable SwiftUI ComponentsBuilding Reusable SwiftUI Components
Building Reusable SwiftUI Components
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroesFirebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroes
 
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
 
async/await in Swift
async/await in Swiftasync/await in Swift
async/await in Swift
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple Developers
 
Building Apps with SwiftUI and Firebase
Building Apps with SwiftUI and FirebaseBuilding Apps with SwiftUI and Firebase
Building Apps with SwiftUI and Firebase
 
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebaseRapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
 
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and FirebaseRapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
 
6 Things You Didn't Know About Firebase Auth
6 Things You Didn't Know About Firebase Auth6 Things You Didn't Know About Firebase Auth
6 Things You Didn't Know About Firebase Auth
 
Five Things You Didn't Know About Firebase Auth
Five Things You Didn't Know About Firebase AuthFive Things You Didn't Know About Firebase Auth
Five Things You Didn't Know About Firebase Auth
 
Building High-Quality Apps for Google Assistant
Building High-Quality Apps for Google AssistantBuilding High-Quality Apps for Google Assistant
Building High-Quality Apps for Google Assistant
 
Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google
 
Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on GoogleBuilding Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google
 
What's new in Android Wear 2.0
What's new in Android Wear 2.0What's new in Android Wear 2.0
What's new in Android Wear 2.0
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android Wear
 
Google Play Services Rock
Google Play Services RockGoogle Play Services Rock
Google Play Services Rock
 
Introduction to Android Wear
Introduction to Android WearIntroduction to Android Wear
Introduction to Android Wear
 
Google+ for Mobile Apps on iOS and Android
Google+ for Mobile Apps on iOS and AndroidGoogle+ for Mobile Apps on iOS and Android
Google+ for Mobile Apps on iOS and Android
 

Dernier

FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRFULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRnishacall1
 
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceCALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceanilsa9823
 
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...Niamh verma
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPsychicRuben LoveSpells
 
9892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x79892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x7Pooja Nehwal
 
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Pooja Nehwal
 
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceanilsa9823
 
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceDelhi Call girls
 
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...wyqazy
 

Dernier (9)

FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRFULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
 
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceCALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
 
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
 
9892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x79892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x7
 
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
 
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
 
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
 
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
 

Google Fit, Android Wear & Xamarin

  • 1. Google Fit, Wear & Xamarin Peter Friese @peterfriese Matt Sullivan @mjohnsullivan
  • 2.
  • 3.
  • 4.
  • 7. Are Fitness apps just for runners, cyclists, athletes? Or for those on a mission to get fit and stay healthy?
  • 8. Can we add elements of fitness to everyday apps?
  • 9.
  • 11.
  • 12.
  • 13.
  • 14. Positive impact on physical and emotional wellbeing == positive impact on user experience and happiness
  • 16. Create a Wear app module Design the watch face UI Extend WatchFaceService.Engine Create a companion app 1 2 3 4
  • 17. Watch Face Architecture Wearable App CanvasWatchFaceService Engine WearableConfigActivity WearableListenerService Mobile App MobileConfigActivity
  • 18. Design for square and round Interactive and Ambient Modes Gestures
  • 19. CanvasWatchFaceService.Engine UI Drawing Manually draw onto a Canvas Object Ambient Mode Changes Reduced color space Burn protection Redraw Intervals Once a minute in Ambient – OnTimeTick() Custom for interactive – use a System Timer TimeZone Changes Use a BroadcastReceiver Interactive Watch Faces .SetAcceptsTapEvents() in Builder Override OnTapCommand()
  • 20. Drawing the watch face Background Hour Ticks Step Count Minutes Hand Seconds Hand Hours Hand
  • 21. backgroundScaledBitmap = Bitmap.CreateScaledBitmap(backgroundBitmap,
 width, height, true);
 canvas.DrawBitmap(backgroundScaledBitmap, 0, 0, null);
 
 Drawing the Watch Face - Background
  • 22.
  • 23. var innerTickRadius = centerX - 10;
 var outerTickRadius = centerX;
 for (var tickIndex = 0; tickIndex < 12; tickIndex++)
 {
 var tickRot = (float)(tickIndex * Math.PI * 2 / 12);
 var innerX = (float)Math.Sin(tickRot) * innerTickRadius;
 var innerY = (float)-Math.Cos(tickRot) * innerTickRadius;
 var outerX = (float)Math.Sin(tickRot) * outerTickRadius;
 var outerY = (float)-Math.Cos(tickRot) * outerTickRadius; 
 canvas.DrawLine(centerX + innerX, centerY + innerY,
 centerX + outerX, centerY + outerY, tickPaint);
 }
 
 Drawing the Watch Face - Ticks
  • 24. var width = bounds.Width();
 var height = bounds.Height();
 
 var steps = stepCount.ToString();
 var stepsWidth = stepcountPaint.MeasureText(steps);
 
 var x = width - stepsWidth - stepCountOffset;
 var y = (height + stepCountTextSize) / 2.0f;
 
 canvas.DrawText(steps, x, y, stepcountPaint);
 Drawing the Watch Face - Step Count
  • 25. Ambient mode Reduce color depth Reduce number of non-black pixels Use color for < 5% pixels Watch face updates once a minute - don’t show seconds Save power Interactive Ambient
  • 26. public override void OnDraw(Canvas canvas, Rect bounds)
 {
 DrawFace(canvas, bounds);
 DrawHands(canvas, bounds);
 }
 
 void DrawHands(Canvas canvas, Rect bounds)
 {
 if (!IsInAmbientMode) {
 canvas.DrawLine(centerX, centerY, centerX + secX, centerY + secY, secondPaint);
 }
 
 canvas.DrawLine(centerX, centerY, centerX + minX, centerY + minY, minutePaint);
 } Ambient Mode
  • 27. public override void OnDraw(Canvas canvas, Rect bounds)
 {
 DrawFace(canvas, bounds);
 DrawHands(canvas, bounds);
 }
 
 void DrawHands(Canvas canvas, Rect bounds)
 {
 if (!IsInAmbientMode) {
 canvas.DrawLine(centerX, centerY, centerX + secX, centerY + secY, secondPaint);
 }
 
 canvas.DrawLine(centerX, centerY, centerX + minX, centerY + minY, minutePaint);
 } Ambient Mode No seconds hand in ambient mode
  • 28. void UpdateTimer()
 {
 if (timerSeconds == null) {
 timerSeconds = new System.Threading.Timer(
 state => {
 Invalidate();
 },
 null, dueTime, period
 }
 else {
 if (IsVisible && !IsInAmbientMode) {
 timerSeconds.Change(0, InteractiveUpdateRateMs);
 }
 else {
 timerSeconds.Change(System.Threading.Timeout.Infinite, 0);
 }
 }
 } Ambient Mode / 2
  • 29. void UpdateTimer()
 {
 if (timerSeconds == null) {
 timerSeconds = new System.Threading.Timer(
 state => {
 Invalidate();
 },
 null, dueTime, period
 }
 else {
 if (IsVisible && !IsInAmbientMode) {
 timerSeconds.Change(0, InteractiveUpdateRateMs);
 }
 else {
 timerSeconds.Change(System.Threading.Timeout.Infinite, 0);
 }
 }
 } Ambient Mode / 2 Redraw every second when in interactive mode
  • 30. void UpdateTimer()
 {
 if (timerSeconds == null) {
 timerSeconds = new System.Threading.Timer(
 state => {
 Invalidate();
 },
 null, dueTime, period
 }
 else {
 if (IsVisible && !IsInAmbientMode) {
 timerSeconds.Change(0, InteractiveUpdateRateMs);
 }
 else {
 timerSeconds.Change(System.Threading.Timeout.Infinite, 0);
 }
 }
 } Ambient Mode / 2 Turn timer on in interactive mode off in ambient mode
  • 31. Configuration Activities WEARABLE_CONFIGURATION on Wear COMPANION_CONFIGURATION on Phone DataLayer API Listen for Data Item Events Write DataItems to URI Paths
  • 32. void SaveStepCountStatus(GoogleApiClient googleApiClient, bool stepCountOn) { var putDataMapRequest = PutDataMapRequest.Create("/xfit_watchface"); putDataMapRequest.DataMap.PutBoolean("stepcount", stepCountOn); var putDataRequest = putDataMapRequest.AsPutDataRequest(); putDataRequest.SetUrgent(); WearableClass.DataApi.PutDataItem(googleApiClient, putDataRequest); } Syncing configuration /1
  • 33. void SaveStepCountStatus(GoogleApiClient googleApiClient, bool stepCountOn) { var putDataMapRequest = PutDataMapRequest.Create("/xfit_watchface"); putDataMapRequest.DataMap.PutBoolean("stepcount", stepCountOn); var putDataRequest = putDataMapRequest.AsPutDataRequest(); putDataRequest.SetUrgent(); WearableClass.DataApi.PutDataItem(googleApiClient, putDataRequest); } Syncing configuration /1 URI Path Data Item Key Sync now
  • 34. void OnDataChanged(DataEventBuffer dataEvents) { foreach (var dataEvent in dataEvents) { var dataItem = dataEvent.DataItem; if (dataItem.Uri.Path == "/xfit_watchface") { var dataMap = DataMapItem.FromDataItem(dataItem).DataMap; displayStepCount = dataMap.GetBoolean(“stepcount”); Invalidate(); // force redraw } } } Syncing configuration /2
  • 35. void OnDataChanged(DataEventBuffer dataEvents) { foreach (var dataEvent in dataEvents) { var dataItem = dataEvent.DataItem; if (dataItem.Uri.Path == "/xfit_watchface") { var dataMap = DataMapItem.FromDataItem(dataItem).DataMap; displayStepCount = dataMap.GetBoolean(“stepcount”); Invalidate(); // force redraw } } } Implements IDataApiDataListener Syncing configuration /2 URI Path Data Item Key
  • 36. Watch face drawing code GoogleAPIClient code Configuration code Reading the step count code 1 2 3 4
  • 38. Partial Classes XFitWatchfaceService XFitWatchFaceEngine (Drawing Code) XFitWatchFaceEngine (Config Code) XFitWatchFaceEngine (Google API Client Code) XFitWatchFaceEngine (Step Count Code) XFitWatchFaceEngine
  • 39. Partial Classes XFitWatchfaceService XFitWatchFaceEngine (Drawing Code) XFitWatchFaceEngine (Config Code) XFitWatchFaceEngine (Google API Client Code) XFitWatchFaceEngine (Step Count Code) XFitWatchFaceEngine [Service(Label = "XFit Watchface 4", Permission = "android.permission.BIND_WALLPAPER")]
 [IntentFilter(new[] { "android.service.wallpaper.WallpaperService" }, Categories = new[] { "com.google.android.wearable.watchface.category.WATCH_FACE" })]
 public partial class XFitWatchfaceService: CanvasWatchFaceService
 {
 
 public override WallpaperService.Engine OnCreateEngine()
 {
 return new XFitWatchfaceEngine(this);
 }
 
 partial class XFitWatchfaceEngine : Engine
 { // drawing code
 } } XFitWatchfaceService.cs (Drawing Code)
  • 40. Partial Classes XFitWatchfaceService XFitWatchFaceEngine (Drawing Code) XFitWatchFaceEngine (Config Code) XFitWatchFaceEngine (Google API Client Code) XFitWatchFaceEngine (Step Count Code) XFitWatchFaceEngine [MetaData( "com.google.android.wearable.watchface.wearableConfigurationAction", Value = "XFitWatchface.CONFIG")]
 [MetaData( "com.google.android.wearable.watchface.companionConfigurationAction", Value = "XFitWatchface.CONFIG")] public partial class XFitWatchfaceService : CanvasWatchFaceService
 {
 
 partial class XFitWatchfaceEngine : Engine, IDataApiDataListener
 {
 void ConnectWatchfaceConfigUpdates() {
 }
 }
 }
 XFitWatchfaceServiceConfig.cs (Config Code)
  • 41. Partial Classes XFitWatchfaceService XFitWatchFaceEngine (Drawing Code) XFitWatchFaceEngine (Config Code) XFitWatchFaceEngine (Google API Client Code) XFitWatchFaceEngine (Step Count Code) XFitWatchFaceEngine public partial class XFitWatchfaceService : CanvasWatchFaceService
 {
 
 partial class XFitWatchfaceEngine : Engine
 {
 GoogleApiClient googleApiClient;
 
 void ConnectGoogleApiClient()
 {
 googleApiClient = new GoogleApiClient.Builder(owner) .AddApi(FitnessClass.HISTORY_API)
 .AddApi(FitnessClass.RECORDING_API)
 .AddApi(WearableClass.API) .Build(); googleApiClient.Connect();
 }
 }
 } XFitWatchfaceServiceGoogleApiClient.cs (Google API Client)
  • 43.
  • 44. Activity Read/Write Body Read/Write Location Read/Write Nutrition Read/Write
  • 45. Sleep Duration & Type Calories Consumed, Macronutrients Height, Weight, BMI, Body Fat % Heart Rate Distance Traveled Steps Calories Burned Activity Segments (walking, running, biking) Gym Activities ACTIVITY NUTRITION BODY SLEEP
  • 47. SENSORS API Find all sensors, both on and off-device FindDataSources (GoogleApiClient c, DataSourcesRequest r) Register for sensor data Add (GoogleApiClient c, SensorRequest r, IOnDataPointListener l); Unregister for sensor data Remove (GoogleApiClient c, IOnDataPointListener l);
  • 48. RECORDING API Stop recording data types/sources Unsubscribe (GoogleApiClient c, DataType t) Unsubscribe (GoogleApiClient c, DataSource s) What data is being recorded ListSubscriptions (GoogleApiClient c) Record from data types/sources Subscribe (GoogleApiClient c, DataType t) Subscribe (GoogleApiClient c, DataSource s)
  • 49. HISTORY API Manually add data InsertData (GoogleApiClient c, DataSet d) Remove data DeleteData (GoogleApiClient c, DeleteDataRequest r) Retrieve data void ReadData (GoogleApiClient c, DataReadRequest r)
  • 50. SESSIONS API Start recording a live session void StartSession(GoogleApiClient client, Session session); Stop recording a live session void StopSession (GoogleApiClient client, String identifier); Insert a session void InsertSession (GoogleApiClient client, SessionInsertRequest request)
  • 51. curl -H "Content-Type: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" https://www.googleapis.com/fitness/v1/users/me/dataSources/ derived:com.google.step_count.delta:...:estimated_steps/ datasets/1438701040000000000-143930584000000000 REST API
  • 53. Create a GoogleApiClient Ensure device is recording steps Build an aggregated query Read and extract the data 1 2 3 4
  • 54. void BuildApiClient () { googleApiClient = new GoogleApiClient.Builder (this) .AddApi (FitnessClass.HISTORY_API) .AddApi (FitnessClass.RECORDING_API) .AddScope (FitnessClass.ScopeActivityReadWrite) .EnableAutoManage (this, AuthClientId, result => { // Unresolvable error, handle or fail silently }) .Build (); SubscribeToSteps (); ReadSteps (); } Read before connection established Auto manage connection Build API Client
  • 55. void SubscribeToSteps () { FitnessClass.RecordingApi.Subscribe (googleApiClient, TypeStepCountDelta) .SetResultCallback( (IResult result) => { if (!result.Status.IsSuccess) { // Error subscribing, handle } }); } Subscribing
  • 56. // Read step count deltas from the History API DataReadRequest DailyStepsForWeek() { long midnight = TimeUtility.MidnightLocalPosix (); long midnightWeekAgo = TimeUtility.DaysAgoPosix (midnight, 7); return new DataReadRequest.Builder () .Aggregate (DataType.TypeStepCountDelta, DataType.AggregateStepCountDelta) .BucketByTime (1, TimeUnit.Days) .SetTimeRange (midnightWeekAgo, midnight, TimeUnit.Milliseconds) .Build(); } Data Aggregation Data Read Request
  • 57. // Reads and extracts step data void ReadDailySteps () { DataReadRequest readRequest = RequestBuilder.DailyStepsForWeek (); FitnessClass.HistoryApi.ReadData (googleApiClient, readRequest) .SetResultCallback ( (IResult result) => { IList<Bucket> buckets = ((DataReadResult)result).Buckets; foreach (var bucket in buckets) { var stepCount = bucket.DataSets.Sum(dataSet => dataSet.DataPoints.Sum (dp => dp.DataType.Fields.Sum (f => dp.GetValue (f).AsInt()))); Log.Info (Tag, $"Step Count: {stepCount}"); } }); } Reading Data Extracting Data Read Daily Steps
  • 59. // Writing data googleApiClient = new GoogleApiClient.Builder(context) .AddApi(...) .AddConnectionCallbacks( connectionHint => { // Connected! }, cause => { // Suspended } ).Build(); Writes require an established connection Writing Data
  • 61. Create a GoogleApiClient Ensure device is recording steps Build an aggregated query Read and extract the data 1 2 3 3
  • 62. Create a GoogleApiClient Ensure device is recording steps Read and extract the data 1 2 2
  • 63. // All in one reading steps void AllInOne() { var client = new GoogleApiClient.Builder (this) .AddApi (FitnessClass.HISTORY_API) .UseDefaultAccount () .Build (); client.Connect (); FitnessClass.HistoryApi.ReadDailyTotal (client, TypeStepCountDelta) .SetResultCallback ( (IResult result) => { DataSet ds = ((DailyTotalResult) result).Total; int stepCount = ds.DataPoints.Sum ( dp => dp.DataType.Fields.Sum ( f => dp.GetValue (f).AsInt())); }); } Default Account Read Daily Total Read Today’s Steps