WCSession发送消息给出错误“无法传递有效载荷”
本文关键字:有效 消息 错误 出错 WCSession | 更新日期: 2023-09-27 18:17:45
我正在使用Xamarin开发Apple Watch应用程序。我正在尝试通过我的SendMessage
功能从我的手表发送消息到iPhone。当我这样做时,我得到out
错误的消息payload could not be delivered
。我只能读取消息的一部分("payload could n…"),因为我把它写在一个标签上(因为我的调试器在Xamarin中不起作用,所以我不能看消息),但是在做了一些谷歌搜索之后,我假设它是这样写的。知道为什么吗?下面是我的代码:
public sealed class WCSessionManager : NSObject, IWCSessionDelegate
{
// 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);
public event MessageReceivedHandler MessageReceived;
public delegate void MessageReceivedHandler(Dictionary<string, object> message, Action<Dictionary<string, object>> replyHandler);
private WCSession validSession
{
get
{
#if __IOS__
// Even though session.Paired and session.WatchAppInstalled are underlined, it will still build as they are available on the iOS version of WatchConnectivity.WCSession
Console.WriteLine($"Paired status:{(session.Paired ? '✓' : '✗')}'n");
Console.WriteLine($"Watch App Installed status:{(session.WatchAppInstalled ? '✓' : '✗')}'n");
return (session.Paired && session.WatchAppInstalled) ? session : null;
//return session;
#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}");
}
}
[Export("sessionReachabilityDidChange:")]
public 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);
UpdateApplicationContextOnSession(NSApplicationContext);
}
catch (Exception ex)
{
Console.WriteLine($"Exception Updating Application Context: {ex.Message}");
}
}
}
public void GetApplicationContext()
{
UpdateApplicationContext(new Dictionary<string, object>() { { "GET", null } });
}
[Export("session:didReceiveApplicationContext:")]
public 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();
IEnumerable<object> values;
try
{
values = applicationContext.Values.Select(v => JsonConvert.DeserializeObject(v.ToString(), typeof(DoorWatchDTO)));
}
catch (Exception)
{
values = applicationContext.Values.Select(v => JsonConvert.DeserializeObject(v.ToString()));
}
var dictionary = keys.Zip(values, (k, v) => new { Key = k, Value = v })
.ToDictionary(x => x.Key, x => x.Value);
ApplicationContextUpdated(session, dictionary);
}
}
[Export("session:didReceiveMessage::")]
public void DidReceiveMessage(WCSession session, NSDictionary<NSString, NSObject> message, WCSessionReplyHandler replyHandler)
{
if (MessageReceived != null)
{
var keys = message.Keys.Select(k => k.ToString()).ToArray();
IEnumerable<object> values;
values = message.Values.Select(v => JsonConvert.DeserializeObject(v.ToString()));
var dictionary = keys.Zip(values, (k, v) => new { Key = k, Value = v })
.ToDictionary(x => x.Key, x => x.Value);
MessageReceived(dictionary, (dict) =>
{
var NSValues = dict.Values.Select(x => new NSString(JsonConvert.SerializeObject(x))).ToArray();
var NSKeys = dict.Keys.Select(x => new NSString(x)).ToArray();
var NSDict = NSDictionary<NSString, NSObject>.FromObjectsAndKeys(NSValues, NSKeys);
replyHandler.Invoke(NSDict);
});
}
}
public void SendMessage(Dictionary<string, object> message, Action<Dictionary<string, object>> replyHandler, WKInterfaceLabel label)
{
if (validSession != null)
{
try
{
var NSValues = message.Values.Select(x => new NSString(JsonConvert.SerializeObject(x))).ToArray();
var NSKeys = message.Keys.Select(x => new NSString(x)).ToArray();
var NSMessage = NSDictionary<NSString, NSObject>.FromObjectsAndKeys(NSValues, NSKeys);
var reply = new WCSessionReplyHandler((replyMessage) =>
{
var values = replyMessage.Values.Select(x => JsonConvert.SerializeObject(x)).ToArray();
var keys = replyMessage.Keys.Select(x => x.ToString()).ToArray();
var dict = keys.Zip(values, (k, v) => new { Key = k, Value = v })
.ToDictionary(x => x.Key, x => (object)x.Value);
replyHandler.Invoke(dict);
});
validSession.SendMessage(NSMessage, reply, (error) =>
{
label.SetText(error.ToString()); // I can see the error in here: "payload could n..."
});
}
catch (Exception ex)
{
Console.WriteLine($"Exception sending message: {ex.Message}");
}
}
}
private void UpdateApplicationContextOnSession(NSDictionary<NSString, NSObject> NSApplicationContext)
{
NSError error;
var sendSuccessfully = validSession.UpdateApplicationContext(NSApplicationContext, out error);
if (sendSuccessfully)
{
Console.WriteLine($"Sent App Context from {Device} 'nPayLoad: {NSApplicationContext.ToString()} 'n");
#if __IOS__
Logging.Log("Success, payload: " + NSApplicationContext.ToString());
#endif
}
else
{
Console.WriteLine($"Error Updating Application Context: {error.LocalizedDescription}");
#if __IOS__
Logging.Log("error: " + error.LocalizedDescription);
#endif
}
}
#endregion
我解决了。我没有实现IWCSessionDelegate
,而是简单地实现WCSessionDelegate
,并根据需要重写函数。