Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to check if user has accepted Bluetooth permission? #26

Open
edwinfinch opened this issue Nov 17, 2016 · 5 comments
Open

How to check if user has accepted Bluetooth permission? #26

edwinfinch opened this issue Nov 17, 2016 · 5 comments

Comments

@edwinfinch
Copy link

edwinfinch commented Nov 17, 2016

In our on-boarding process there are completion handlers for permission requests so that we can make sure that the permission was granted before moving onto the next on-boarding step.

With PebbleKit however, calling the run function for the first time will launch the permission request though we have no way of knowing when the user finished choosing their option on the following popup which asks them for permission.

What is the most reliable way for us to check whether or not the user has accepted the permission?

Thanks!

@maxbaeumle
Copy link

Hi Edwin,

Try this:

    CBPeripheralManagerAuthorizationStatus status = [CBPeripheralManager authorizationStatus];
    if (status == CBPeripheralManagerAuthorizationStatusNotDetermined) {
        // Not determined
    } else if (status == CBPeripheralManagerAuthorizationStatusAuthorized) {
        // Authorized
    } else if (status == CBPeripheralManagerAuthorizationStatusDenied) {
        // Denied
    } else if (status == CBPeripheralManagerAuthorizationStatusRestricted) {
        // Restricted
    }

There is no way I know of to subscribe to authorization changes so you need something like this:

    for (NSUInteger index = 0; index < 10; index++) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(index * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            // Update status
        });
    }

@drodriguez
Copy link
Contributor

The idea of the run method was that developers can ask for authorization on their own terms, and only start running PBPebbleCentral when they got the authorization from the users.

In our app, we have a central object that handles calling -[PBPebbleCentral run]. The method will be called if one of this conditions happen:

  • CBPeripheralManager.authorizationStatus != CBPeripheralManagerAuthorizationStatusNotDetermined
  • There is a -[PBPebbleCentral lastConnectedWatch]
  • The user allows the authorization (see below).

When the user reaches the point in the app that we have explained that we will ask for the BT permissions, the same object has a method requestAuthorizationWithCompletion:, in this method we first check the authorizationStatus again, and then proceed or not with the authorization.

  • If Restricted or Denied we show an error to the user.
  • If Authorized we consider that the user accepted, and start PBPebbleCentral without showing extra UI (this should not technically happen, but we have it there anyway).
  • If NotDetermined, we simply create a CBPeripheralManager that should popup the authorization. Since you can give a delegate and a queue to this CBPeripheralManager, you can receive the changes in peripheralManagerDidUpdateState:, which allows you to avoid the active polling that Max is recommending above.

I might be able to expand some of those explanations, but I hope it makes everything a little bit clearer.

In summary: we don’t give you a tool to ask for authorization, since one solution doesn’t work for everybody, but you don’t need to interact with PebbleKit to ask for the authorization. The idea behind -[PBPebbleCentral run] was that you only call it when your app was ready to connect to Bluetooth devices.

@maxbaeumle
Copy link

maxbaeumle commented Nov 17, 2016

@drodriguez Thanks for explaining the design decisions behind this. However, PBPebbleCentral doesn't expose the internal delegate methods. You need additional code that creates your own instance of CBPeripheralManager, so you can (and should) use the delegate.

@maxbaeumle
Copy link

Still, CBPeripheralManagerState is not equal to CBPeripheralManagerAuthorizationStatus, for which a delegate method doesn't exist if you need updates to it.

@drodriguez
Copy link
Contributor

@maxbaeumle sorry I wasn’t clear in the last part.

Yes, you need to create your own CBPeripheralManager. It is the only way I know to make the OS authorization alert to popup. The first time you create one of those and you are in NotDetermined, the popup will happen. PBPebbleCentral doesn’t create any of those until you call run, to allow you to ask for authorization in your own terms. You don’t need access to the CBPeripheralManager inside PBPebbleCentral at all.

Since you create your own CBPeripheralManager you provide your own delegate and your own delegate queue. The only one you need in this case is peripheralManagerDidUpdateState:, the updates sent there will inform you about the changes to the authorizationStatus.

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheralManager {
  CBManagerState state = peripheralManager.state;

  switch (state) {
    case PBPeripheralManagerStateUnknown: {
      // pass on this, an update is imminent (according to docs)
      break;
    }
    case PBPeripheralManagerStateUnsupported: {
      // the user device is too old, LE will never work, Classic will still work, so you probably want to run PBPebbleCentral anyway.
      break;
    }
    case PBPeripheralManagerStateUnauthorized: {
      // the user didn’t authorize LE
      break;
    }
    case PBPeripheralManagerStateResetting:
    case PBPeripheralManagerStatePoweredOff:
    case PBPeripheralManagerStatePoweredOn: {
      // Either of this three tells you that the authorization was successful
      break;
    }
  }
}

You can also check for authorizationStatus inside that method and advance when it switches out of NotDetermined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants