【问题标题】:WCSession Send Message gives error "payload could not be delivered"WCSession 发送消息给出错误“无法传递有效负载”
【发布时间】:2016-11-12 04:11:49
【问题描述】:

我正在使用 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

【问题讨论】:

    标签: c# ios xamarin watchkit


    【解决方案1】:

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-12
    • 2018-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多