How to verify Bluetooth permissions (race condition)

Hello Dear All,
I have read the articles about Bluetooth + Google API 31 and I tried to do it accordingly, but there is something I failed to solve. What I want to do:

  • When start my app, ask for necessary Bluetooth permissions.
  • If the user grants (or already granted) them, check if BT is enabled and if not, enable BT using an Activitystarter
  • Let the user select the Bluetooth server to connect to

Please see the attached .aia. Test cases:

  1. If no permission given yet, the application starts and immediately drops a runtime error and ends (I attached the screenshot) but also asks for the Bluetooth (close devices) permission. If the user gives the permission, next time the application runs nicely (see step 2)
  2. If the permissions were granted, if BT is enabled, then you can immediately see the servers in the list. If the BT is not enabled, then the app asks for enabling BT then also runs nicely.

Of course I know why the runtime error happens. In the Scree.Initialize() function I start asking the BT permissions but immediately after I try to enable Bluetooth which is not going to happen if there are no permissions. However, I simply cannot check if the permissions were given or not.

I was thinking at first that I only need to ask for permission and if the permission was given or the user just gave it, then I was going to go to the Screen.PermissionGranted() but it's not the case. I only get to Screen.PermissionGranted() if the user just gave the permission. That is why the app drops the runtime error and asks for the permission at the same time.

The question is, how can I do it nicely? I want to enable Bluetooth if not enabled, BUT only in that case when the permissions are ready (otherwise I'd like to drop an error message to the user that without the permissions we cannot continue. I believe it's possible if I test in Screen.ErrorOccured() for ErrorNumber 908 or 517 or 506).

I have tested with Samsung Galaxy s10E Android v12 (last update 01/12/2022), One UI version 4.1

Could you please help, maybe?
BT_test_copy.aia (4.5 KB)

If you are asking for help, I recommend you to make it as easy for others to be able to help you ...
You probably will get more feedback then...

which means in your case post a screenshot of your relevant blocks...

To download the aia file, upload it to App Inventor, open it, do some bug hunting for you, etc... this takes time, and most people will not do that...
Thank you.

Taifun


Trying to push the limits! Snippets, Tutorials and Extensions from Pura Vida Apps by icon24 Taifun.

Yes, of course, if that helps resolving the issue. I upload the Screen.Initialize() and Screen.PermissionGranted(), I feel them relevant. The other blocks are only related when you click on the "Connect" button (I call it "btselect") and that part works OK. The debug() function only write to the textbox on the screen.


This is the init block. As you see, I ask for permission but immediately after, if Bluetooth is not enabled, I use the Activitystarter to enable BT.

  • If the permissions were not given yet, the Activitystarter drops a runtime error and closes the app. At the same time the phone asks the user for the permission but it's too late for the ActivityStarter.
  • If the permissions were given already, it works, as (I believe) the Screen.AskForPermission does not do anything; at the same time the ActivityStarter enables Bluetooth.

I tried to handle the error using Screen.Erroroccured(), it doesn't work.

The latest picture is only a screenshot so you can have an overview how it looks like.
screenshot

Thank you.

Dear @Atomgep, what about if you enable a clock that executes the ActivityStarter only (for example) 1 second after the "call debug" ?

image
In other words, put the
image
into a clock and enable that clock (with a period of 1000) only after the call debug. Then, once executed, the clock must disable itself, obviously.
This will give time (1 sec) to "something else" to happen and only after that time is elapsed, the Activity Starter will run.
Several times I've seen that leaving some time to "unknown" tasks solves the issue.
Maybe this is not the case, but giving it a chance, it costs 2 min's.
Best, Ugo.

Dear Ugo,

thank you for the tip, I tried it out. Unfortunately, it dropped the same runtime error, only one seconds later, while the user (simulated by me this time) still tried to understand what his phone wants from him again. You may say I should increase the time to 10 seconds. That may solve the problem when the permissions are not granted, which is a one-time action, or at least it's very infrequent. For a change, after giving the permissions, the user need to wait for 10 seconds every time he/she forgot to enable Bluetooth. Also, maybe 10 seconds are not enough...

I hope there is some solution to better check for permissions.

I was also thinking on enabling Bluetooth only when the user clicks on the "Connect" ListPicker. I almost believed I found a good solution; however the ListPicker only has two methods that can be used here; .TouchDown() or .BeforePicking() as I have to enable BT, then populate the Listpicker with the list of available BT devices nearby. All of this before the listpicker list appears.

The result was an empty list and when I closed it down, the notification from my phone appeared that the application wants to enable Bluetooth. I enabled it and the Listpicker worked at the second time but this is not user friendly again. I still believe this can be the solution because I could separate the permission request and the ActivityStarter action from each others. Do you have some tricks, maybe? :slight_smile:

Here are the related methods:


(BTStatus just writes to the screen next to the button, nothing important there.)

Cheers, Atomgep

Hello All,

finally I think I came to the solution. I added a button and hid the "btselect" ListPicker.


At the beginning, I simply ask for the permission "Bluetooth_connect".

If it's granted, I ask for the "Bluetooth_scan" (needed).

If the user clicks to a button, and BT is not enabled, I start the activity. If the BT is enabled, I just open the Lispicker's list.
activitystarter_afteractivity
After the activity enabled BT successfully, of course I also need to open that listpicker.

...and finally, if the user did not give the permission, I'm going to get error 908 so I have to handle it. I let the user know that BT permission is missing and I disable the button.

Finally, if the user says "no" to enable BT, the activitystarter handles it gracefully, the listpicker will not shown.
And that was it, folks.
Thanks for everyone who commented and read.
Cheers, Atomgep

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.