NSInputStream 从不在 iOS9 上使用 HasBytesAvailable(经典蓝牙)
NSInputStream never HasBytesAvailable on iOS9 (classic Bluetooth)
我有一个跨平台 (Xamrin) 应用程序,可以进行一些 classic 蓝牙通信,并且在 iOS8 上运行得非常好。但是,在 iOS9 上重建并 运行 它之后,我无法让 NSInputStream 永远拥有 "HasBytesAvailable"= true。注:I followed all the instructions from Xamarin's website.
我尝试将委托分配给 InputStream 并等待 NSRunLoop,但流似乎从来没有可用字节。该事件仅在输入流打开时触发(在 iOS9 上)(在 iOS8 上按预期触发)。
这是在 iOS8 上成功读取的代码片段(委托方法):
EAsession.InputStream.Delegate = new Foo();
EAsession.InputStream.Schedule(NSRunLoop.Current,NSRunLoop.NSDefaultRunLoopMode);
EAsession.InputStream.Open();
(NSRunLoop.Current).RunUntil(NSDate.FromTimeIntervalSinceNow(2));
其中 Foo 是一个 class,它实现了:NSObject、INSStreamDelegate
public class Foo :NSObject, INSStreamDelegate
{
[Export("stream:handleEvent:")]
public void HandleEvent(Foundation.NSStream theStream, Foundation.NSStreamEvent streamEvent)
{
//Code to read bytes here
}
为了确保确实有字节发送到 iPhone5 我修改了外部蓝牙设备以仅回显接收到的任何字节。
在 iOS8 上使用任一方法(委托或等待 NSRunLoop),回显立即到达。但是,当我将目标设备更改为 iOS9 时,我可以永远等待,而 HasBytesAvailable 将始终为 false。
我什至尝试读取,不管 HasBytesAvailable 是否为假,但没有读取任何内容(我想这没什么大惊喜)。
此外,我尝试使用 Xcode6.4 和 Xcode 7 进行构建,结果相同。
目前我没有想法所以任何帮助将不胜感激!
提前致谢!
编辑:
我联系了 Xamarin,我正在为他们编写一个测试应用程序来测试它是 Apple 问题还是 Xamarin 问题。
另外,请参阅 this link 中关于蓝牙的评论...也许相关?
我可以通过打开一个我无意使用的 EAAccessory 的 InputStream 来解决这个问题。我的猜测是,作为新 iOS9 蓝牙合同的一部分,输入流和输出流都是必需的。这是我的工作代码的相关更新:
accessory.Delegate = new EAAccessoryDelegateHandler ();
if (PrinterSession == null)
{
PrinterSession = new EASession (accessory, PrintProtocol);
}
var mysession = PrinterSession;
mysession.InputStream.Open();
mysession.OutputStream.Delegate = this;
mysession.OutputStream.Schedule (NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
mysession.OutputStream.Open ();
然后,当我关闭 OutputStream 时,我会立即关闭未使用的 InputStream。
所以我终于解决了,
我不完全确定最终问题是什么,因为我做了一些事情:
- Xamarin beta 流更新(5.9.7 build 12)。
- 更新到最新的iOS (9.0.2)
- 使用Xcode7.0
- 并更改我呼叫代表的位置、打开流和时间表。
代码的变化是,我不再在接收和发送方法中分别处理打开、调度和委托分配,而是在同一个地方处理。也就是说,在创建 EASession 时,我像这样分配了以上所有内容:
s = new EASession(device, protocol);
output_stream = s.OutputStream;
input_stream = s.InputStream;
output_stream.Delegate=this;
output_stream.Schedule(NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
output_stream.Open();
input_stream.Delegate = this;
input_stream.Schedule(NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
input_stream.Open();
目前我没有取消输入和输出流的计划,我不确定这是正确的做法。当我从工作转向一个漂亮的代码时,我会尽量保持更新...
与 Bluecode 描述的不同,我确实需要使用我的输入流,而且我总是打开它;所以我不确定这是否是同一个问题。我仍然不确定问题的解决方案是什么,因为它可以是上述一种方法,也可以是上述方法的组合。稍后当我有更多时间查看哪个是单一解决方案时,我可能会对此进行更多实验?如果有的话。
希望对您有所帮助。
干杯
我有一个跨平台 (Xamrin) 应用程序,可以进行一些 classic 蓝牙通信,并且在 iOS8 上运行得非常好。但是,在 iOS9 上重建并 运行 它之后,我无法让 NSInputStream 永远拥有 "HasBytesAvailable"= true。注:I followed all the instructions from Xamarin's website.
我尝试将委托分配给 InputStream 并等待 NSRunLoop,但流似乎从来没有可用字节。该事件仅在输入流打开时触发(在 iOS9 上)(在 iOS8 上按预期触发)。
这是在 iOS8 上成功读取的代码片段(委托方法):
EAsession.InputStream.Delegate = new Foo();
EAsession.InputStream.Schedule(NSRunLoop.Current,NSRunLoop.NSDefaultRunLoopMode);
EAsession.InputStream.Open();
(NSRunLoop.Current).RunUntil(NSDate.FromTimeIntervalSinceNow(2));
其中 Foo 是一个 class,它实现了:NSObject、INSStreamDelegate
public class Foo :NSObject, INSStreamDelegate
{
[Export("stream:handleEvent:")]
public void HandleEvent(Foundation.NSStream theStream, Foundation.NSStreamEvent streamEvent)
{
//Code to read bytes here
}
为了确保确实有字节发送到 iPhone5 我修改了外部蓝牙设备以仅回显接收到的任何字节。
在 iOS8 上使用任一方法(委托或等待 NSRunLoop),回显立即到达。但是,当我将目标设备更改为 iOS9 时,我可以永远等待,而 HasBytesAvailable 将始终为 false。
我什至尝试读取,不管 HasBytesAvailable 是否为假,但没有读取任何内容(我想这没什么大惊喜)。
此外,我尝试使用 Xcode6.4 和 Xcode 7 进行构建,结果相同。
目前我没有想法所以任何帮助将不胜感激!
提前致谢!
编辑:
我联系了 Xamarin,我正在为他们编写一个测试应用程序来测试它是 Apple 问题还是 Xamarin 问题。
另外,请参阅 this link 中关于蓝牙的评论...也许相关?
我可以通过打开一个我无意使用的 EAAccessory 的 InputStream 来解决这个问题。我的猜测是,作为新 iOS9 蓝牙合同的一部分,输入流和输出流都是必需的。这是我的工作代码的相关更新:
accessory.Delegate = new EAAccessoryDelegateHandler ();
if (PrinterSession == null)
{
PrinterSession = new EASession (accessory, PrintProtocol);
}
var mysession = PrinterSession;
mysession.InputStream.Open();
mysession.OutputStream.Delegate = this;
mysession.OutputStream.Schedule (NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
mysession.OutputStream.Open ();
然后,当我关闭 OutputStream 时,我会立即关闭未使用的 InputStream。
所以我终于解决了,
我不完全确定最终问题是什么,因为我做了一些事情:
- Xamarin beta 流更新(5.9.7 build 12)。
- 更新到最新的iOS (9.0.2)
- 使用Xcode7.0
- 并更改我呼叫代表的位置、打开流和时间表。
代码的变化是,我不再在接收和发送方法中分别处理打开、调度和委托分配,而是在同一个地方处理。也就是说,在创建 EASession 时,我像这样分配了以上所有内容:
s = new EASession(device, protocol);
output_stream = s.OutputStream;
input_stream = s.InputStream;
output_stream.Delegate=this;
output_stream.Schedule(NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
output_stream.Open();
input_stream.Delegate = this;
input_stream.Schedule(NSRunLoop.Current, NSRunLoop.NSDefaultRunLoopMode);
input_stream.Open();
目前我没有取消输入和输出流的计划,我不确定这是正确的做法。当我从工作转向一个漂亮的代码时,我会尽量保持更新...
与 Bluecode 描述的不同,我确实需要使用我的输入流,而且我总是打开它;所以我不确定这是否是同一个问题。我仍然不确定问题的解决方案是什么,因为它可以是上述一种方法,也可以是上述方法的组合。稍后当我有更多时间查看哪个是单一解决方案时,我可能会对此进行更多实验?如果有的话。
希望对您有所帮助。 干杯