Potential Permissions Problems

Can we get some documentation for when this fails? All of the built-in components should be doing the right thing and we need to know when they aren't so we can fix it.

2 Likes

To reproduce this issue try this simple example:
permissions_test.aia (24.7 KB)

I'm not sure if it is allowed to post a download link for an APK to Google Drive:

To me this just demonstrates that the system is behaving as expected. The LocationSensor1’s Enabled property is set in the designer so it requests permission if it isn’t yet granted. It may be the case that it doesn’t yet have a fix in Screen1.Initialize so CurrentAddress may not work there.

Extension developers are responsible for requesting the permission at a time they think is appropriate. App Inventor cannot anticipate when that might be so it’s up to the author of the extension to make the appropriate allowance. Am I missing something @Taifun about how the extension is supposed to work?

this is correct
in this case the extension developer was lazy and didn't implement it... :grin:

Taifun

Hi Evan,

One of many approaches I tried to automate multiple permission requests was the simple one of putting conditional ask for permission statements into the permission granted block see image below, This didn’t seem to work and was similar to an issue in a link provided in response to the original post. https://groups.google.com/forum/#!searchin/mitappinventortest/permission$20screen.initialize|sort:date/mitappinventortest/UiIfA0mgXV4/Q9fS5NzoDAAJ

Today I find that the approach does now work. I don’t know whether I made a mistake yesterday, but to day it seems the solution to multiple automatic permission requests is very straightforward.

If I did make a mistake yesterday then apologies to all.

Regards, Peter

image

P.S. The example given is not intended to be a full implementation just to illustrate the point that the ability to use conditional calls for permission in PermissionGranted and PermissionNotGranted blocks makes the automation task feasible and straightforward.

I would expect that all necessary permissions are requested without having to reload the screen several times.

In this example I have to reload the screen twice so that all permissions are granted and the sound is played:
permissions_test2.aia (106.1 KB)

PS : I put the sound file in the assets (for testing).

I'm talking about the "LocationSensor" component that requests "ACCESS_FINE_LOCATION", which is done automatically, without needing to be specifically requested (there is no need to ask on Screen.Initialize). In this case I have to reload the screen several times to get all needed permissions.
Your approach doen't work in this case, but maybe you can prove the opposite.

Yes, if I remove the LocationSensor component and use the BLE extension instead, it works.

PS: I only use components, no extension:

1 Like

Anke wrote: <Your approach doen’t work in this case, but maybe you can prove the opposite> .

Hi Anke,
I tested the location sensor component permission using a test method copied below and with the aia attached. I believe this confirms your finding that including the location sensor by itself over-rides/disables/bypasses a variety of permissions in the Screen1 initialisation.
Regards, Peter

Test method
It’s a stacked multi permission version of my earlier method. It had no other sensor than the location sensor and no extensions.In the test below I disabled the two Screen1.AskForPermission to ACCESS_FINE_LOCATION. instructions.

Test and results
On start up the test forced a request "Allow’Push to access this device’s location? DENY ALLOW ". (App Inventor calls all my apps ‘PushTo’). I tried denying and allowing the permission and in both cases the permissions in Screen1.Initialise were unable to run and I had to use a manual permission button to run the file permission that in turn ran the stacked permissions.
Without the location sensor the app worked either providing direct requests for permission or indirect requests to set permissions in the phone. I’ve attached an aia file in case my description is unclear to anyone.

The aia images
image
image
image

PermissionTest1.aia (22.2 KB)

1 Like

I carried out a different set of tests on the start up permission to ACCESS_FINE_LOCATION using labels and timers in the Screen1.initalise block and it seems clear that:

  • The independent start up permission to ACCESS_FINE_LOCATION takes priority over the Screen1 Initialise procedure.
  • No more than one permission request is allowed on the screen at a time.
  • Permission requests are not queued
  • The start up ACCESS_FINE_LOCATION request does not provide a PermissionGranted call back

I’m not a programmer so have to ask:

  • Are my dot point descriptions correct?
  • Do they reflect normal behaviour for a start up permission request?
  • Are there other start up permission requests that operate in the same way?
    and
  • Does this mandate the need for a manual trigger (e.g. list picker or button) to set permissions?

Thanks for any advice on this, Regards, Peter

1 Like

Exactly, so it's a bug.

1 Like

Yes, however, I noticed the following:

If I deny ACCESS_FINE_LOCATION, the Screen1.PermissionDenied event is triggered and eg WRITE_EXTERNAL_STORAGE is requested.

But of course that doesn't solve the problem and doesn't help in any way.

Yes. Let me explain more deeply:

Every component can optionally define an Initialize method that is called just prior to Screen's Initialize event. In the LocationSensor, this is used to request permission if it isn't granted. Since the permissions mechanism is modal, once we start a permission request the user needs to complete the workflow before the next request is made. Therefore, the presence of the LocationSensor (only if Enabled property is true) results in it being the first permission dialog shown. Further, because Screen's Initialize event is called immediately after the components initialize, the workflow hasn't been completed so the additional requests are ignored because one is already in progress.

Yes, but this is true of any Android app as the dialog is presented by the system, not the application.

Correct. As before, the goal here is that the developer shouldn't need to manage permissions at all. All of the components should request permission at the appropriate times and we have done a lot of auditing to try and ensure this is the case. The purpose of the AskForPermission block as envisioned was twofold: 1) Allow app developers to handle PermissionDenied events by explaining to the user (e.g., using the Notifier) why a permission was needed and then re-ask for permission and 2) allow an "escape hatch" for developers using extensions that needed dangerous permissions but had not been updated by their authors to use the new internal APIs we provided for extension developers. It was never intended to be used to request many permissions upfront as this is generally considered bad form in the app world (for example, Apple reserves the right to not publish apps that use this type of model if the permission isn't critical to the functioning of the app).

When we did the update to handle the permissions model, we decided not to call the PermissionsGranted event in the cases where the permission request was made at the request of a component as everything was "working as intended" in this scenario. That event is intended solely for explicit handling of requests made by calls to AskForPermission. On the other hand PermissionDenied could come from the user denying either an implicit or explicit permission request, so it is called in all scenarios.

On the one hand, the block was never intended to be used in this way but rather within the context of PermissionDenied. On the other hand, it seems like it might be useful to queue many calls to AskForPermission since inevitably people will misuse it in this way. Internally queuing the requests seems like the best option as it removes the management of the pending permission queue as a burden from the developer. However, we have to think about this interacts with the PermissionDenied event as now there is a potential interaction between having one or more permissions denied and needing UI to explain why permissions are needed.

1 Like

EWPatton wrote <It was never intended to be used to request many permissions upfront as this is generally considered bad form in the app world (for example, Apple reserves the right to not publish apps that use this type of model if the permission isn’t critical to the functioning of the app)>

Hi
Thanks for those explanations. I hadn’t realised that a request for multiple critical permissions upfront was considered bad form. I had hoped to avoid incoveniencing the app user by placing the requests at the start of a program so that it didn’t distract them when they were first learning to use the app. Would using a listpicker up front to request multiple critical permissions be acceptable? Otherwise I can include a suggestion in the read me document to alert the user to expect the requests during the app’'s operation unless they preempt this by setting the permissions up manually before using the app.
Regards, Peter

The way I’ve typically seen this done in other apps (mostly using iOS as an example since that’s my daily driver), is that they will show a screen explaining some functionality of the app “MyAwesomeApp helps you navigate to your favorite spots. We use your location to do so, but we need you to accept the next prompt for this to work.” (or something like that) with a next button that then causes the prompt to appear. Once they’ve accepted, you show another screen explaining the next thing, and so on. Generally though, it’s better to ask at the time when the permission is needed if it’s not critical to the functioning of the app.

Further reading:

1 Like

Thanks for the detailed explanations.
But why doesn’t this work specially with ACCESS_FINE_LOCATION?

Or in other words:
If multiple permissions are requested at Screen.Initialize (except ACCESS_FINE_LOCATION), they will be queried one after another. However, when ACCESS_FINE_LOCATION is requested at Screen.Initialize, more permissions on Screen.Initialize are no longer requested.

In the Screen1.Initialize block for my example I include multiple permission requests, but my tests showed that only one would be executed as they cannot be executed simultaneously and are not queued. This is whether or not the location sensor is in the app.
The reason I have the multiple requests at Screen.Initialize is so that if any permissions have not already been queried and granted then the first of these will be triggered and its corresponding PermissionGranted event will trigger a cyclical cascade of permission requests and PermissionGranted events until all are accepted or declined.

Then please post an AIA (which describes and explains the problem) so that I can reproduce it.

Hi Anke,I was suggesting an answer to your question <But why doesn’t this work specially with ACCESS_FINE_LOCATION> ? My suggestion arose from the tests I carried out before writing the example that I gave earlier - I should have posted the example again to make that clear so I’ve copied it below and supplied an aia as requested.

PermissionTest.aia (22.2 KB)

To clarify my previous post - When I place multiple Screen.AskPermission statements in a ScreenInitialisation block they are not queried one after another - only one is queried whether or not a Locationsensor component is present. I think this is normal operation as its been confirmed in the previous discussion that Permission requests are not queued.

PermissionTest4.aia (20.0 KB)
MultiPermissionsTest4