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

WCSession发送消息给出错误“无法传递有效载荷”

我解决了。我没有实现IWCSessionDelegate,而是简单地实现WCSessionDelegate,并根据需要重写函数。