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

Failed to add service after bluetooth disconnect and re-advertising. #302

Open
cjzamora opened this issue Jun 29, 2016 · 22 comments
Open

Failed to add service after bluetooth disconnect and re-advertising. #302

cjzamora opened this issue Jun 29, 2016 · 22 comments
Labels

Comments

@cjzamora
Copy link

cjzamora commented Jun 29, 2016

What should i do to avoid this error and re-advertise my device after bluetooth disconnect, what i'm doing is i manually disable my bluetooth, re-enable it again then start advertising again?

@randdusing
Copy link
Owner

I don't think you need to re-add the service after disconnecting. Try calling removeAllServices before calling addService again.

@cjzamora
Copy link
Author

Thanks man i will try that, i can't go around with other cordova plugins for bluetooth because this is more stable that the others, great work by the way man!

@cjzamora
Copy link
Author

Man thanks for your help, it is working properly now. 👍

@cjzamora
Copy link
Author

It seems like the callback from initializePeripheral does not execute again after re-advertisement when the device bluetooth is re-connected.

@randdusing
Copy link
Owner

You should only need to call initializePeripheral once. Then use start/stopAdvertising to toggle advertising on and off.

@randdusing
Copy link
Owner

Oh I just realized what your last comment was saying. So if you connect a device, disconnect and then connect again, you're not receiving any events?

@cjzamora
Copy link
Author

cjzamora commented Jul 12, 2016

Yea, after disconnect then reconnect, the initializePeripheral does not emit events anymore like connection and disconnection events. It only happens if i turn off then turn on the bluetooth. I was able to advertise but i can't receive any events anymore for connect and disconnect.

@avenavo
Copy link

avenavo commented Oct 26, 2018

I have the similar issue - only on Xiaomi Redmi Note 3
When i turn off/on bluetooth on device then i'm getting "Failed to add service" error even when it is called after removeAllServices

@mattkhaw
Copy link
Contributor

@randdusing Any updates on this issue? I'm also experiencing the same thing. Upon further checking the code, I think the most likely answer is on Android side, the initPeripheralCallback is not implemented during state change for Bluetooth hence, the initializePeripheral callbacks aren't working. It seems that initialize callbacks are working because it is tied to the broadcast receiver but for peripheral, it is not. So, I think that's the main issue.

@avenavo Did you solve this issue? I've also been getting this problem. From logcat, I think it is due to DeadObjectException.

@mattkhaw
Copy link
Contributor

@randdusing I think I've found the solution to this. The solution is pretty simple. Here's the link that explains it. I think the plugin is required to be updated. This only affects Android. iOS seems fine.

TLDR; The proposed solution is to recreate the gattServer when bluetooth is turned on. When turned off, it is mandatory to dispose the current instance of gattServer. I've tried it and it seemed to work.

I've also added callbacks when the adapter's state changed for initializePeripheral as well. As you mentioned before, initialize is required to be called for Android before initializePeripheral anyways. So, I think it is safe to put the callback for initializePeripheral anyways.

@randdusing
Copy link
Owner

This should be fixed thanks to @mattkhaw's PR: #607

@a-sac
Copy link
Contributor

a-sac commented Jul 15, 2020

Hello @randdusing @mattkhaw ,

This issue still affects me (I updated the plugin). When I turn off the bluetooth and turn it back on, and then I add a service, it always returns 'failed to add service'. Everything works except adding a service (I removed all services before trying to create a new one).
If I want to add a service, I have to restart the app.

@leoproject
Copy link

Hey guys @randdusing @mattkhaw ,

I have same problem that @a-sac. I tried the same steps mentioned here, but I couldn't. Anyway, congratulations on your work !! I will wait for an answer this, thanks. :)

@mattkhaw
Copy link
Contributor

I couldn't definitively say that this is the solution but this is what works for me.

You need to start and stop advertising based on peripheral state otherwise, you will get that error. This is most likely due to the peripheral portion is shutting down or hasn't shut down fully. So, you need to make sure about that.

In order to do so, when peripheral is in disabled state, just check whether Bluetooth is enabled or not. If yes, just stop advertising, otherwise skip. When peripheral is enabled, just remove the services you want to remove and add them back again and of course, start advertising.

If there's any errors when you add or start advertising, just ignore them. This happens because the services you might want to add already exist or those services is advertising already.

Everything I've stated here is based on the PR I posted and I didn't update since and it still works fine.

@a-sac
Copy link
Contributor

a-sac commented Jul 16, 2020

So, this is what I'm doing:

  1. enable
  2. initialize
  3. initializePeripheral
  4. removeAllServices
  5. addService
  6. startAdvertising

Then I turn off the bluetooth. Then I check if ble is enabled, which is not, so I don't stop advertising. Then I start it again, and we go back to step 1.
It all works well except addService.
If I ignore the errors, I'm able to start advertising but the central device cant find the service to write :/

Is there any way I can 'reset' the plugin or something like that during app time ? (since restarting the app is a solution")

Btw, I removed enable, because it would enable bluetooth without the user authorization. Initialize does that, but when I turn off/on the bluetooth it won't request. It only requests the first time :/
Maybe these issues are correlated. Both addService and Initiliaze work well the first time, and always if we don't turn off bluetooth. But when we turn on/off the bluetooth, both of them have issues. Maybe something is not working or being reset when bluetooth is powered off, idk.

@a-sac
Copy link
Contributor

a-sac commented Jul 16, 2020

Hey there,

I don't know what happened but it started working. As you said, the first time it returns an error when I start advertising, but then it starts working.

I'm still having that issue wit initialize tho.

@mattkhaw
Copy link
Contributor

mattkhaw commented Jul 17, 2020

Hey there,

I don't know what happened but it started working. As you said, the first time it returns an error when I start advertising, but then it starts working.

I'm still having that issue wit initialize tho.

To answer this, no. That's not what I've said. If first time there's errors, this means that you are not doing it correctly. Refer to the comment below on how to initialize properly.

If there's any errors when you add or start advertising, just ignore them. This happens because the services you might want to add already exist or those services is advertising already.

This is what I said. I didn't tell you to ignore the errors. I stated that only ignore IF you know that the services you want to add exist or are already advertising.

So, this is what I'm doing:

  1. enable
  2. initialize
  3. initializePeripheral
  4. removeAllServices
  5. addService
  6. startAdvertising

Then I turn off the bluetooth. Then I check if ble is enabled, which is not, so I don't stop advertising. Then I start it again, and we go back to step 1.
It all works well except addService.
If I ignore the errors, I'm able to start advertising but the central device cant find the service to write :/

The reason why the central device is unable to find the service is due to advertising error. You cannot call advertising functions if your Bluetooth is disabled.

When your Bluetooth is disabled, it automatically stops advertising but the plugin's state for advertising is still enabled. Unfortunately, this is a bug for the plugin. @randdusing should update this. But I think it is easily solved by just setting the variable to false based on Bluetooth state. If I have the time, I'll probably do it. For the time being, just use ble.isEnabled instead of ble.isAdvertising.

Reason why ble.addService is not working is because there's an error in the whole chain. Most likely due to the fact that the service exists at this point. This is caused by not disabling Bluetooth correctly.

Now I see what's the problem. Your event sequence seems to be incorrect.

As per documentation, initialize and initializePeripheral functions needed to be done once. Hence, it is not required to be called every time when Bluetooth is enabled. So, you only need to call when your app is initializing.

When app init:

  1. initialize
  2. initializePeripheral

That's the whole operation. You don't need to proceed any further with calling other functions for now. As I've stated in my previous post, from here on out, you only need to play around with Bluetooth state.

When peripheral is enabled:

  1. removeService
  2. addService
  3. startAdvertising

When peripheral is disabled:

  1. stopAdvertising

If you do all this correctly, it should be working as intended. This is basically the same as what I've said previously.

Is there any way I can 'reset' the plugin or something like that during app time ? (since restarting the app is a solution")

Restarting the app is not a solution. It never will be a thing. It is our job to make sure the app we are developing works as intended regardless of the tools we used to create it. If your app requires a restart, then something is definitely wrong. And no, there's no way to reset.

Btw, I removed enable, because it would enable bluetooth without the user authorization. Initialize does that, but when I turn off/on the bluetooth it won't request. It only requests the first time :/

Btw, I have to remind you that the documentation does state on iOS, there's no such thing as enabling/disabling bluetooth programmatically. So, if your app supports iOS as well, then your current logic won't work at all. So, back to square one.

And yes, when you initialize the plugin, you can pass in "request: true" if you want the plugin to prompt a message for that. Then it should have the message every time. The reason why this is disabled by default is because you might have a custom interface for enabling/disabling bluetooth. On iOS, since there's no command to enable/disable programatically, all you can do is just ask the user to enable thru the device's control panel. From my experience, better just to leave out that request param.

Maybe these issues are correlated. Both addService and Initiliaze work well the first time, and always if we don't turn off bluetooth. But when we turn on/off the bluetooth, both of them have issues. Maybe something is not working or being reset when bluetooth is powered off, idk.

Refer to the above comment for this. It is related to the incorrect sequence of events.

Sorry for the lengthy post. If my choice of words offended you, I do apologise. But do keep in mind that I am in the same boat as you when I first started to figure out all of this but tbh, Bluetooth is very finicky about its event sequences. One wrong sequence, then the whole thing doesn't work.

@randdusing
Copy link
Owner

@mattkhaw Is the "subissue" you tagged me on only affecting Android? I no longer have an Android device, so I may not be able to fix it. PRs welcome :)

@mattkhaw
Copy link
Contributor

@randdusing I haven't look at the iOS source code yet. I can confirm it is affecting the Android code. I'll check it out later.

@mattkhaw
Copy link
Contributor

@randdusing Okay, I've checked. It only affects Android. iOS doesn't have an explicit boolean for this. I'll see whether I can test it out. I'll send a PR once it is done.

@MojioMS
Copy link
Contributor

MojioMS commented Aug 13, 2020

I do also experience a Failed to add service-error after turning bluetooth off and on. My procedure is

  1. initialize (on android)
  2. initializePeripheral
  3. removeAllServices
  4. addService

if I then turn off bluetooth and turn it on again, i start again at step 3, removing all services, but on step 4 i receive the Failed to add service-error.
Is anywhere a minimalistic working example, which allows adding a service successfully after turning bluetooth off and on?

@mattkhaw
Copy link
Contributor

@MojioMS I've posted my solution in my previous post. It's considered to be a step by step guide. If you follow it correctly, you will get the desired outcome.

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

No branches or pull requests

7 participants