apple / swift-nio

Event-driven network application framework for high performance protocol servers & clients, non-blocking.
https://swiftpackageindex.com/apple/swift-nio/documentation
Apache License 2.0
7.98k stars 652 forks source link

Not working Watch OS 9 on real Apple Watch #2255

Closed umasankar421 closed 2 years ago

umasankar421 commented 2 years ago

We are using mqtt-nio which internally uses this swift-nio framework. When we are testing on watch OS 9 beta, we couldn't establish the connection to mqtt server. Its working fine on a watchOS 9 beta simulator but on a real watch its not working.

This is the issue created on Mqtt-Nio https://github.com/swift-server-community/mqtt-nio/issues/121 for the reference.

adam-fowler commented 2 years ago

Just for some details here. It throwing a connectTimeout error. AsyncHTTPClient is also exhibiting the same issue. In both situations they will be connecting using NIOTransportServices and NIOTSConnectionBootstrap to make the connection.

dnadoba commented 2 years ago

Can you try connection to https://apple.com using URLSession instead of AsyncHTTPClient to see if this is a general networking error:

import Foundation
let (data, response) = try await URLSession.shared.data(from: URL(string: "https://apple.com/")!)
print(response)
print(String(decoding: data, as: UTF8.self))

If this doesn't work this is probably not an issue with NIO.

Also worthwhile mentioning is that if you want to connection to a local address or over http instead of https you will need to add some configuration to your Info.plist as documented here: https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity/nsallowslocalnetworking https://developer.apple.com/documentation/bundleresources/information_property_list/nsapptransportsecurity

Lukasa commented 2 years ago

Please also note that data connectivity from the watch in this fashion is only available if you are marked as an audio streaming app.

Lukasa commented 2 years ago

For further debugging it would be very helpful if you could provide a sample project that reproduces the issue.

umasankar421 commented 2 years ago

@dnadoba Thanks for the reply. I have tried basic networking calls in WatchApp using URLSession. They work fine both in WatchOS Simulator and a real watch.

@Lukasa Thanks for the reply. I am sharing sample project code here

in this project, I am creating a MQTT Session using MQTT NIO framework. This works fine in WatchOS 9 Simulator but not working in WatchOS 9 real Apple Watch.

Same issue mentioned here as well (https://github.com/swift-server-community/mqtt-nio/issues/121)

Appreciate your help on this issue. Thank you.

umasankar421 commented 2 years ago

@Lukasa and @dnadoba @adam-fowler

We are seeing the same behavior in iOS 16 and WatchOS 9 versions in a real apple iPhone and Watch. However, working fine in Simulator.

Lukasa commented 2 years ago

To be clear, you're seeing this in iOS 16?

umasankar421 commented 2 years ago

It's working in IOS 16. The issue is in WatchOS 9 only that too on a real apple watch.

Lukasa commented 2 years ago

Can you confirm that your app has started an audio streaming session? If it has not, NIO-based applications will not function.

umasankar421 commented 2 years ago

We are not using any audio streaming session.

This sample code works fine in WatchOS 8 for both Simulator and real watch app and all iOS Device and simulators.

But this is not working on WatchOS 9 real apple watch but working fine in WatchOS 9 Simulator.

Also, Please share some sample usage of how to start audio streaming session for this NIO?

agnosticdev commented 2 years ago

Sorry to jump in on this thread abruptly, but @Lukasa is correct here. Low level networking, whether that be a socket or a TCP / UDP connection with NWConnection is not expected to consistently work on watchOS without an audio streaming session. See more on this here. The reason for this is to preserve the battery and performance of the watchOS device. And so to preserve this performance a network policy is enforced on the device for low level networking to only to be done in the context of an audio stream session, like with AVAudioSession with policy: .longFormAudio set on the category. This allows low level networking to pull in meta data or audio data related to the audio stream if needed in this specific context. Regarding you previous thread, you may see low level networking work here and there on a standalone watchOS app that is not connected to the iOS device, but chances are it will not be consistent. An example of this is navigating away from the watch app performing network connection and then back to the app a few seconds later. I suspect in this situation you will run into a bunch of NECP failures.
Having said all of that above, it is recommended that for higher level user space networking that is done on a watchOS app outside the context of an audio streaming session, to use an APIs like URLSession instead. Specifically URLSessionDataTask.

umasankar421 commented 2 years ago

This works perfectly fine in WatchOS 8,7 versions. But stopped working on WatchOS9. So wanted to understand, are there any API changes happened specific in WatchOS9. Please confirm. Thank you.

agnosticdev commented 2 years ago

This works perfectly fine in WatchOS 8,7 versions. But stopped working on WatchOS9. So wanted to understand, are there any API changes happened specific in WatchOS9. Please confirm. Thank you.

After some internal discussions it looks like this was not the intended behavior in watchOS 7 or 8 and this is now resolved in watchOS 9 thus explaining what you are seeing. I would encourage you to open a bug report for updated documentation on this so that this info is not just on the Developer Forums but also in our Developer Documentation as well.

agnosticdev commented 2 years ago

Please post your Feedback ID here for your bug report.

agnosticdev commented 2 years ago

As an update to this topic; there was a new Technote that was created with this updated information - TN3135: Low-level networking on watchOS