NSInputStream never HasBytesAvailable on iOS9 (classic bluetooth)

I have a cross platform (Xamrin) app that does classic bluetooth communication and works great on iOS8. However, after restoring and running it on iOS9, I cannot get the NSInputStream to ever have "HasBytesAvailable" = true. Note: I followed all instructions from the Xamarin.

I tried both assign delegate to InputStream and wait on NSRunLoop, but the stream doesn't seem to have any bytes available. The event only fires (on iOS9) when the input stream is opened (on iOS8 it fires as expected).

Here is a code snippet that successfully reads iOS8 (delegate method):

EAsession.InputStream.Delegate = new Foo();    
EAsession.InputStream.Schedule(NSRunLoop.Current,NSRunLoop.NSDefaultRunLoopMode);
    EAsession.InputStream.Open();           
    (NSRunLoop.Current).RunUntil(NSDate.FromTimeIntervalSinceNow(2));

      

Where Foo is the class that implements: NSObject, INSStreamDelegate

    public class Foo :NSObject, INSStreamDelegate
{
    [Export("stream:handleEvent:")]
    public void HandleEvent(Foundation.NSStream theStream, Foundation.NSStreamEvent streamEvent)
    {
      //Code to read bytes here
    }

      

To verify that there are actually bytes sent to the iPhone5, I modified the external bluetooth device to simply respond to all received bytes.

Using any method (delegate or pending on NSRunLoop) on iOS8, echo comes immediately. However, when I change the target device to iOS9, I can always wait, and HasBytesAvailable will always be false.

I've even tried reading, regardless of whether HasBytesAvailable is false, but nothing is being read (no big surprise I think).

Also, I tried to build using both Xcode6.4 and Xcode 7 with the same result.

I am out of ideas at the moment, so any help would be greatly appreciated!

Thanks in advance!

EDIT:

I have contacted Xamarin and I am writing a test app for them to check if this is an Apple issue or a Xamarin issue.

Also see the comment in this link about bluetooth ... possibly related?

+3


source to share


2 answers


So I finally decided

I'm not really sure what the problem is, in the end I did a few things:

  • Upgrading to Xamarin Beta Stream (5.9.7 build 12).
  • Update to the latest iOS version (9.0.2)
  • Use Xcode 7.0
  • And change where I named the delegate, open flow and schedule.

The code change was that instead of handling the open, scheduling, and delegate assignment in the receive and dispatch methods separately, I did it in the same place. Namely, when creating the EASession, I assigned all of the above like this:



        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();

      

I am not debugging input and output streams at the moment and I am not sure if this is correct. I'll try to keep this update as I move from work to pretty code that works ...

Unlike what Bluecode describes, I definitely needed to use my input stream, and I always had it open; so I'm not sure if the same problem was. I still don't know what the solution is to the problem as it can be either one or a combination of the above. I could experiment a bit with this later when I have more time to see which one was the only solution? If there's.

Hope this helps anyone. Greetings

+1


source


I managed to solve this problem by opening an InputStream in EAAccessory which I was not going to use. My guess is that both inbound and outbound streams are needed as part of the new iOS9 Bluetooth contract. This is the current update to my working code:

            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 ();

      



Then, when I close the OutputStream, I immediately close the unused InputStream.

+1


source







All Articles