Skip to content

Instantly share code, notes, and snippets.

@b099l3
Last active October 17, 2023 21:06
Show Gist options
  • Save b099l3/e5a361477168053f0d58ac3907ea16d6 to your computer and use it in GitHub Desktop.
Save b099l3/e5a361477168053f0d58ac3907ea16d6 to your computer and use it in GitHub Desktop.
A Session manager for watchOS and iOS xamarin. Can be used in both xamarin.iOS and xamarin.watchOS
using System.Collections.Generic;
using System.Linq;
using Foundation;
using Newtonsoft.Json;
using System;
namespace WatchConnectivity
{
public sealed class WCSessionManager : WCSessionDelegate
{
// Setup is converted from https://www.natashatherobot.com/watchconnectivity-say-hello-to-wcsession/
// with some extra bits
private static readonly WCSessionManager sharedManager = new WCSessionManager();
private static WCSession session = WCSession.IsSupported ? WCSession.DefaultSession : null;
#if __IOS__
public static string Device = "Phone";
#else
public static string Device = "Watch";
#endif
public event ApplicationContextUpdatedHandler ApplicationContextUpdated;
public delegate void ApplicationContextUpdatedHandler(WCSession session, Dictionary<string, object> applicationContext);
private WCSession validSession
{
get
{
#if __IOS__
Console.WriteLine($"Paired status:{(session.Paired ? '✓' : '✗')}\n");
Console.WriteLine($"Watch App Installed status:{(session.WatchAppInstalled ? '✓' : '✗')}\n");
return (session.Paired && session.WatchAppInstalled) ? session : null;
#else
return session;
#endif
}
}
private WCSession validReachableSession
{
get
{
return session.Reachable ? validSession : null;
}
}
private WCSessionManager() : base() { }
public static WCSessionManager SharedManager
{
get
{
return sharedManager;
}
}
public void StartSession()
{
if (session != null)
{
session.Delegate = this;
session.ActivateSession();
Console.WriteLine($"Started Watch Connectivity Session on {Device}");
}
}
public override void SessionReachabilityDidChange(WCSession session)
{
Console.WriteLine($"Watch connectivity Reachable:{(session.Reachable ? '✓' : '✗')} from {Device}");
// handle session reachability change
if (session.Reachable)
{
// great! continue on with Interactive Messaging
}
else {
// 😥 prompt the user to unlock their iOS device
}
}
#region Application Context Methods
public void UpdateApplicationContext(Dictionary<string, object> applicationContext)
{
// Application context doesnt need the watch to be reachable, it will be received when opened
if (validSession != null)
{
try
{
var NSValues = applicationContext.Values.Select(x => new NSString(JsonConvert.SerializeObject(x))).ToArray();
var NSKeys = applicationContext.Keys.Select(x => new NSString(x)).ToArray();
var NSApplicationContext = NSDictionary<NSString, NSObject>.FromObjectsAndKeys(NSValues, NSKeys);
NSError error;
var sendSuccessfully = validSession.UpdateApplicationContext(NSApplicationContext, out error);
if (sendSuccessfully)
{
Console.WriteLine($"Sent App Context from {Device} \nPayLoad: {NSApplicationContext.ToString()} \n");
}
else
{
Console.WriteLine($"Error Updating Application Context: {error.LocalizedDescription}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception Updating Application Context: {ex.Message}");
}
}
}
public override void DidReceiveApplicationContext(WCSession session, NSDictionary<NSString, NSObject> applicationContext)
{
Console.WriteLine($"Recieving Message on {Device}");
if (ApplicationContextUpdated != null)
{
var keys = applicationContext.Keys.Select(k => k.ToString()).ToArray();
var values = applicationContext.Values.Select(v => JsonConvert.DeserializeObject(v.ToString())).ToArray();
var dictionary = keys.Zip(values, (k, v) => new { Key = k, Value = v })
.ToDictionary(x => x.Key, x => x.Value);
ApplicationContextUpdated(session, dictionary);
}
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment