Skip to content

Commit cd8c57c

Browse files
committed
[ActivityRings] Minor refactoring
1 parent 606e09a commit cd8c57c

File tree

5 files changed

+96
-183
lines changed

5 files changed

+96
-183
lines changed
Lines changed: 85 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,292 +1,237 @@
11
using System;
22
using System.Collections.Generic;
3-
using WatchKit;
4-
using Foundation;
3+
54
using CoreFoundation;
5+
using Foundation;
66
using HealthKit;
7-
using ObjCRuntime;
8-
7+
using WatchKit;
98

109
namespace ActivityRings.ActivityRingsWatchAppExtension
1110
{
1211
public partial class InterfaceController : WKInterfaceController, IHKWorkoutSessionDelegate
1312
{
14-
1513
public HKHealthStore HealthStore { get; set; } = new HKHealthStore();
1614

1715
public HKWorkoutSession CurrentWorkoutSession { get; set; }
16+
1817
public DateTime WorkoutBeginDate { get; set; }
18+
1919
public DateTime WorkoutEndDate { get; set; }
20+
2021
public bool IsWorkoutRunning { get; set; } = false;
21-
public HKQuery CurrentQuery { get; set; }
22-
public List<HKSample> ActiveEnergySamples { get; set; } = new List<HKSample>();
2322

24-
// Start with a zero quantity.
25-
public HKQuantity CurrentActiveEnergyQuantity { get; set; } = HKQuantity.FromQuantity(HKUnit.Kilocalorie, 0.0);
23+
public HKQuery CurrentQuery { get; set; }
2624

25+
public List<HKSample> ActiveEnergySamples { get; set; } = new List<HKSample> ();
2726

27+
// Start with a zero quantity.
28+
public HKQuantity CurrentActiveEnergyQuantity { get; set; } = HKQuantity.FromQuantity (HKUnit.Kilocalorie, 0.0);
2829

29-
protected InterfaceController(IntPtr handle) : base(handle)
30+
protected InterfaceController (IntPtr handle) : base (handle)
3031
{
3132
// Note: this .ctor should not contain any initialization logic.
3233
}
3334

34-
35-
public override void WillActivate()
35+
public override void WillActivate ()
3636
{
37-
// This method is called when the watch view controller is about to be visible to the user.
38-
3937
// Only proceed if health data is available.
40-
if (!HKHealthStore.IsHealthDataAvailable) { return; };
38+
if (!HKHealthStore.IsHealthDataAvailable)
39+
return;
4140

4241
// We need to be able to write workouts, so they display as a standalone workout in the Activity app on iPhone.
4342
// We also need to be able to write Active Energy Burned to write samples to HealthKit to later associating with our app.
4443

45-
var typesToShare = new NSSet(HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned), HKObjectType.GetWorkoutType());
46-
47-
var typesToRead = new NSSet(HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned));
44+
var typesToShare = new NSSet (HKQuantityType.Create (HKQuantityTypeIdentifier.ActiveEnergyBurned), HKObjectType.GetWorkoutType ());
45+
var typesToRead = new NSSet (HKQuantityType.Create (HKQuantityTypeIdentifier.ActiveEnergyBurned));
4846

49-
HealthStore.RequestAuthorizationToShare(typesToShare, typesToRead, (bool success, NSError error) =>
50-
{
47+
HealthStore.RequestAuthorizationToShare (typesToShare, typesToRead, (bool success, NSError error) => {
5148
if (error != null && !success)
52-
{
53-
Console.WriteLine($"You didn't allow HealthKit to access these read/write data types. In your app, try to handle this error gracefully when a user decides not to provide access. The error was: {error.LocalizedDescription}. If you're using a simulator, try it on a device.");
54-
}
49+
Console.WriteLine ("You didn't allow HealthKit to access these read/write data types. " +
50+
"In your app, try to handle this error gracefully when a user decides not to provide access. " +
51+
$"The error was: {error.LocalizedDescription}. If you're using a simulator, try it on a device.");
5552
});
5653
}
5754

58-
59-
partial void ToggleWorkout()
55+
partial void ToggleWorkout ()
6056
{
61-
if (IsWorkoutRunning){
62-
if (CurrentWorkoutSession != null)
63-
{
64-
HealthStore.EndWorkoutSession(CurrentWorkoutSession);
65-
IsWorkoutRunning = false;
66-
}
67-
68-
}else {
57+
if (IsWorkoutRunning && CurrentWorkoutSession != null) {
58+
HealthStore.EndWorkoutSession (CurrentWorkoutSession);
59+
IsWorkoutRunning = false;
60+
} else {
6961
// Begin workout.
7062
IsWorkoutRunning = true;
7163

7264
// Clear the local Active Energy Burned quantity when beginning a workout session.
73-
CurrentActiveEnergyQuantity = HKQuantity.FromQuantity(HKUnit.Kilocalorie, 0.0);
65+
CurrentActiveEnergyQuantity = HKQuantity.FromQuantity (HKUnit.Kilocalorie, 0.0);
7466

7567
CurrentQuery = null;
76-
ActiveEnergySamples = new List<HKSample>();
68+
ActiveEnergySamples = new List<HKSample> ();
7769

7870
// An indoor walk workout session. There are other activity and location types available to you.
7971

8072
// Create a workout configuration
81-
var configuration = new HKWorkoutConfiguration()
82-
{
73+
var configuration = new HKWorkoutConfiguration {
8374
ActivityType = HKWorkoutActivityType.Walking,
8475
LocationType = HKWorkoutSessionLocationType.Indoor
8576
};
8677

87-
8878
NSError error = null;
89-
CurrentWorkoutSession = new HKWorkoutSession(configuration, out error)
90-
{
79+
CurrentWorkoutSession = new HKWorkoutSession (configuration, out error) {
9180
Delegate = this
9281
};
93-
HealthStore.StartWorkoutSession(CurrentWorkoutSession);
9482

83+
HealthStore.StartWorkoutSession(CurrentWorkoutSession);
9584
}
96-
9785
}
9886

99-
100-
101-
public void SaveWorkout()
87+
public void SaveWorkout ()
10288
{
10389
// Obtain the `HKObjectType` for active energy burned.
104-
var activeEnergyType = HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned);
90+
var activeEnergyType = HKQuantityType.Create (HKQuantityTypeIdentifier.ActiveEnergyBurned);
10591
if (activeEnergyType == null) return;
10692

10793
var beginDate = WorkoutBeginDate;
10894
var endDate = WorkoutEndDate;
10995

110-
TimeSpan timeDifference = endDate.Subtract(beginDate);
96+
var timeDifference = endDate.Subtract (beginDate);
11197
double duration = timeDifference.TotalSeconds;
11298
NSDictionary metadata = null;
11399

114-
var workout = HKWorkout.Create(HKWorkoutActivityType.Walking,
100+
var workout = HKWorkout.Create (HKWorkoutActivityType.Walking,
115101
(NSDate)beginDate,
116102
(NSDate)endDate,
117103
duration,
118104
CurrentActiveEnergyQuantity,
119-
HKQuantity.FromQuantity(HKUnit.Mile, 0.0),
105+
HKQuantity.FromQuantity (HKUnit.Mile, 0.0),
120106
metadata);
121107

122108
var finalActiveEnergySamples = ActiveEnergySamples;
123109

124110
if (HealthStore.GetAuthorizationStatus(activeEnergyType) != HKAuthorizationStatus.SharingAuthorized ||
125-
HealthStore.GetAuthorizationStatus(HKObjectType.GetWorkoutType()) != HKAuthorizationStatus.SharingAuthorized
126-
)
127-
{
111+
HealthStore.GetAuthorizationStatus(HKObjectType.GetWorkoutType()) != HKAuthorizationStatus.SharingAuthorized)
128112
return;
129-
}
130113

131-
HealthStore.SaveObject(workout, (success, error) =>
132-
{
133-
if (!success)
134-
{
135-
Console.WriteLine($"An error occured saving the workout. In your app, try to handle this gracefully. The error was: {error.ToString()}.");
114+
HealthStore.SaveObject(workout, (success, error) => {
115+
if (!success) {
116+
Console.WriteLine ($"An error occured saving the workout. In your app, try to handle this gracefully. The error was: {error}.");
136117
return;
137118
}
138119

139-
if (finalActiveEnergySamples.Count > 0)
140-
{
141-
HealthStore.AddSamples(finalActiveEnergySamples.ToArray(), workout, (addSuccess, addError) =>
142-
{
120+
if (finalActiveEnergySamples.Count > 0) {
121+
HealthStore.AddSamples (finalActiveEnergySamples.ToArray (), workout, (addSuccess, addError) => {
143122
// Handle any errors
144123
if (addError != null)
145-
Console.WriteLine($"An error occurred adding the samples. In your app, try to handle this gracefully. The error was: {error.ToString()}.");
146-
124+
Console.WriteLine ($"An error occurred adding the samples. In your app, try to handle this gracefully. The error was: {error.ToString()}.");
147125
});
148126
}
149-
150127
});
151-
152128
}
153129

154-
155-
public void BeginWorkout(DateTime beginDate)
130+
public void BeginWorkout (DateTime beginDate)
156131
{
157132
// Obtain the `HKObjectType` for active energy burned and the `HKUnit` for kilocalories.
158-
var activeEnergyType = HKQuantityType.Create(HKQuantityTypeIdentifier.ActiveEnergyBurned);
159-
if (activeEnergyType == null) return;
133+
var activeEnergyType = HKQuantityType.Create (HKQuantityTypeIdentifier.ActiveEnergyBurned);
134+
if (activeEnergyType == null)
135+
return;
160136

161137
var energyUnit = HKUnit.Kilocalorie;
162138

163139
// Update properties.
164140
WorkoutBeginDate = beginDate;
165-
workoutButton.SetTitle("End Workout");
141+
workoutButton.SetTitle ("End Workout");
166142

167143
// Set up a predicate to obtain only samples from the local device starting from `beginDate`.
168144

169-
var datePredicate = HKQuery.GetPredicateForSamples((NSDate)beginDate, null, HKQueryOptions.None);
145+
var datePredicate = HKQuery.GetPredicateForSamples ((NSDate)beginDate, null, HKQueryOptions.None);
170146

171-
var devices = new NSSet<HKDevice>(new HKDevice[] { HKDevice.LocalDevice });
147+
var devices = new NSSet<HKDevice> (new HKDevice[] { HKDevice.LocalDevice });
172148
var devicePredicate = HKQuery.GetPredicateForObjectsFromDevices(devices);
173-
var predicate = NSCompoundPredicate.CreateAndPredicate(new NSPredicate[] { datePredicate, devicePredicate });
174-
175-
149+
var predicate = NSCompoundPredicate.CreateAndPredicate (new NSPredicate[] { datePredicate, devicePredicate });
176150

177151
//Create a results handler to recreate the samples generated by a query of active energy samples so that they can be associated with this app in the move graph.It should be noted that if your app has different heuristics for active energy burned you can generate your own quantities rather than rely on those from the watch.The sum of your sample's quantity values should equal the energy burned value provided for the workout
178-
179152
Action <List<HKSample>> sampleHandler;
180-
sampleHandler = (List<HKSample> samples) =>
181-
{
182-
DispatchQueue.MainQueue.DispatchAsync(delegate
183-
{
184-
List<HKQuantitySample> accumulatedSamples = new List<HKQuantitySample>();
185-
186-
var initialActivityEnergy = CurrentActiveEnergyQuantity.GetDoubleValue(energyUnit);
153+
sampleHandler = (List<HKSample> samples) => {
154+
DispatchQueue.MainQueue.DispatchAsync (delegate {
155+
var accumulatedSamples = new List<HKQuantitySample> ();
187156

157+
var initialActivityEnergy = CurrentActiveEnergyQuantity.GetDoubleValue (energyUnit);
188158
double accumulatedValue = initialActivityEnergy;
189-
foreach (HKQuantitySample sample in samples)
190-
{
191-
accumulatedValue = accumulatedValue + sample.Quantity.GetDoubleValue(energyUnit);
192-
var ourSample = HKQuantitySample.FromType(activeEnergyType, sample.Quantity, sample.StartDate, sample.EndDate);
193-
accumulatedSamples.Add(ourSample);
194-
159+
foreach (HKQuantitySample sample in samples) {
160+
accumulatedValue = accumulatedValue + sample.Quantity.GetDoubleValue (energyUnit);
161+
var ourSample = HKQuantitySample.FromType (activeEnergyType, sample.Quantity, sample.StartDate, sample.EndDate);
162+
accumulatedSamples.Add (ourSample);
195163
}
196164

197165
// Update the UI.
198-
CurrentActiveEnergyQuantity = HKQuantity.FromQuantity(energyUnit, accumulatedValue);
199-
activeEnergyBurnedLabel.SetText(String.Format("{0}", accumulatedValue));
166+
CurrentActiveEnergyQuantity = HKQuantity.FromQuantity (energyUnit, accumulatedValue);
167+
activeEnergyBurnedLabel.SetText ($"{accumulatedValue}");
200168

201169
// Update our samples.
202-
ActiveEnergySamples.AddRange(accumulatedSamples);
203-
204-
170+
ActiveEnergySamples.AddRange (accumulatedSamples);
205171
});
206172
};
207-
208173

209174
// Create a query to report new Active Energy Burned samples to our app.
210-
var activeEnergyQuery = new HKAnchoredObjectQuery(activeEnergyType, predicate, null, HKSampleQuery.NoLimit, (query, addedObjects, deletedObjects, newAnchor, error) =>
211-
{
212-
// Valid?
213-
if (error == null)
214-
{
175+
var activeEnergyQuery = new HKAnchoredObjectQuery (activeEnergyType, predicate, null,HKSampleQuery.NoLimit, (query, addedObjects, deletedObjects, newAnchor, error) => {
176+
if (error == null) {
215177
// NOTE: `deletedObjects` are not considered in the handler as there is no way to delete samples from the watch during a workout
216178
ActiveEnergySamples = new List<HKSample>(addedObjects);
217179
sampleHandler(ActiveEnergySamples);
218180

181+
} else {
182+
Console.WriteLine ($"An error occured executing the query. In your app, try to handle this gracefully. The error was: {error}.");
219183
}
220-
else {
221-
Console.WriteLine($"An error occured executing the query. In your app, try to handle this gracefully. The error was: {error.ToString()}.");
222-
}
223-
224184
});
225185

226186
// Assign the same handler to process future samples generated while the query is still active.
227-
activeEnergyQuery.UpdateHandler = (query, addedObjects, deletedObjects, newAnchor, error) =>
228-
{
229-
230-
if (error == null)
231-
{
232-
233-
ActiveEnergySamples = new List<HKSample>(addedObjects);
187+
activeEnergyQuery.UpdateHandler = (query, addedObjects, deletedObjects, newAnchor, error) => {
188+
if (error == null) {
189+
ActiveEnergySamples = new List<HKSample> (addedObjects);
234190
sampleHandler(ActiveEnergySamples);
235-
236-
}
237-
else {
238-
Console.WriteLine($"An error occured executing the query. In your app, try to handle this gracefully. The error was: {error.ToString()}.");
191+
} else {
192+
Console.WriteLine ($"An error occured executing the query. In your app, try to handle this gracefully. The error was: {error}.");
239193
}
240-
241194
};
242195

243196
// Start Query
244197
CurrentQuery = activeEnergyQuery;
245-
HealthStore.ExecuteQuery(activeEnergyQuery);
246-
198+
HealthStore.ExecuteQuery (activeEnergyQuery);
247199
}
248200

249-
250-
251-
public void EndWorkout(DateTime endDate)
201+
public void EndWorkout (DateTime endDate)
252202
{
253203
WorkoutEndDate = endDate;
254-
workoutButton.SetTitle("Begin Workout");
255-
activeEnergyBurnedLabel.SetText("0.0");
256-
if (CurrentQuery != null)
257-
{
204+
workoutButton.SetTitle ("Begin Workout");
205+
activeEnergyBurnedLabel.SetText ("0.0");
206+
if (CurrentQuery != null) {
258207
var query = CurrentQuery;
259208
HealthStore.StopQuery(query);
260209
}
261-
SaveWorkout();
262-
}
263210

211+
SaveWorkout ();
212+
}
264213

265-
public void DidChangeToState(HKWorkoutSession workoutSession, HKWorkoutSessionState toState, HKWorkoutSessionState fromState, NSDate date)
214+
public void DidChangeToState (HKWorkoutSession workoutSession, HKWorkoutSessionState toState, HKWorkoutSessionState fromState, NSDate date)
266215
{
267-
DispatchQueue.MainQueue.DispatchAsync(delegate
268-
{
216+
DispatchQueue.MainQueue.DispatchAsync (delegate {
269217
// Take action based on the change in state
270-
switch (toState)
271-
{
272-
218+
switch (toState) {
273219
case HKWorkoutSessionState.Running:
274-
BeginWorkout((DateTime)date);
220+
BeginWorkout ((DateTime)date);
275221
break;
276222
case HKWorkoutSessionState.Ended:
277-
EndWorkout((DateTime)date);
223+
EndWorkout ((DateTime)date);
278224
break;
279225
default:
280-
Console.WriteLine($"Unexpected workout session: {toState}.");
226+
Console.WriteLine ($"Unexpected workout session: {toState}.");
281227
break;
282228
}
283229
});
284-
285230
}
286231

287-
public void DidFail(HKWorkoutSession workoutSession, NSError error)
232+
public void DidFail (HKWorkoutSession workoutSession, NSError error)
288233
{
289-
Console.WriteLine($"An error occured with the workout session. In your app, try to handle this gracefully. The error was: {error}.");
234+
Console.WriteLine ($"An error occured with the workout session. In your app, try to handle this gracefully. The error was: {error}.");
290235
}
291236
}
292237
}

watchOS/ActivityRings/ActivityRings/ActivityRings.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler>
2828
<MtouchTlsProvider>Default</MtouchTlsProvider>
2929
<PlatformTarget>x86</PlatformTarget>
30+
<CodesignKey>iPhone Developer</CodesignKey>
3031
</PropertyGroup>
3132
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
3233
<DebugType>pdbonly</DebugType>

0 commit comments

Comments
 (0)