Jump to content
KMarb

RequestPermissions - Trying to understand threading (better)

Recommended Posts

My android app (Delphi 11) wants to download a file to the external storage download folder. I call the line below:

 

  PermissionsService.RequestPermissions([FPermissionReadExternalStorage, FPermissionWriteExternalStorage], ExternalStoragePermissionRequestResult, externalStorageRationale);

 

I understand the call to requestPermissions happens asynchronously. When user accepts or rejects the request, the following handler runs:

 

procedure TDMCommon.ExternalStoragePermissionRequestResult(Sender: TObject; const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray);
begin
  if (Length(AGrantResults) = 2) and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) then
    begin
      toast ('Downloading file...', shortToast);

      AsyncDownload.Download(FileURL, LocalFilename, asyncDownloadFinished) then
...

 

I've chopped out code I feel is not relevant.

 

Here are my questions:

  1 - The handler is not running in the main thread, correct?

  2 - If 1 is correct, then I should not call "toast" directly like it's shown, correct? I should call TThread.Queue(nil, procedure begin toast... end);?

  3 - I'm downloading a file in the background using the AsyncDownload code (taken from one of the Delphi samples). It works great when run from main thread, but, if the handler is running code in a secondary thread (not the main thread), is it a bad idea to kickoff another thread to download a file? Could I just initiate a synchronous download here?

 

I'm having some strange behavior and trying to get things right.

 

The strangeness:

  - running in debug mode, sometimes I end up with a "CPU" window where I'm stepping through assembly code... I'm not sure what can cause that.

  - I set breakpoints in the finally section of "Try" blocks, but the breakpoints never fire, as if the "finally" blocks are not actually executing. I have calls to log.d in the finally and they do execute, so I think things are fine, but execution does not pause at my breakpoint.

 

Any light on the subject is much appreciated.

 

Keith

Share this post


Link to post
2 hours ago, KMarb said:

1 - The handler is not running in the main thread, correct?

Incorrect - the permissions handler runs in the main thread. You can easily test this with:

if TThread.CurrentThread.ThreadID = MainThreadID then
  // Is in the main thread

Not sure what is causing your debugger issues.

Share this post


Link to post

awesome! Thank you. Follow up question:

 

I'm testing on an android 11 device, a uleFone Armor X9. The permission handler shows that both read and write external storage have been granted.

 

I'm getting a permission error when I try to download a file to the shared downloads folder:

 

  if (Length(AGrantResults) = 2) and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) then
    begin

// both are granted...

  UpdateFileName := extractFNFromURL (UpdateURL);
  UpdateFullFilename := TPath.Combine(TPath.GetSharedDownloadsPath, UpdateFileName);

 

  // I get a permission denied on the following line, not sure if the error is triggered by the fileExists function or request to DeleteFile.

  if fileExists (UpdateFullFilename) then TFile.Deletefile (UpdateFullFilename);

 

  Is this possibly related to android 11 changes with shared storage?

Share this post


Link to post

One other question... If I have started a process using TTask.Run, and then within that thread I RequestPermission, then the permission handler is running in the context of the TTask thread, not the main thread, correct?

Share this post


Link to post
32 minutes ago, KMarb said:

Is this possibly related to android 11 changes with shared storage?

Yes. This link may have some useful information regarding this.

31 minutes ago, KMarb said:

If I have started a process using TTask.Run, and then within that thread I RequestPermission

Do not request permissions outside of the main thread. I'm not sure why you think you need to.

Share this post


Link to post

Thank you for the link.

 

Re: when permissions are requested, it's not that I think I need to request outside the main thread, but the logic makes more sense to me to request the permission within the task that downloads the file.

 

IE, within the task, request permission to save to external storage, then if not granted, save the downloaded file to private storage

 

rather than:

 

request permission to save to external storage

start task to download a file.

 

Do you think it's a problem to request permissions outside the main ui?

Share this post


Link to post
1 minute ago, KMarb said:

Re: when permissions are requested, it's not that I think I need to request outside the main thread, but the logic makes more sense to me to request the permission within the task that downloads the file.

It makes more sense to request the permissions within the UI thread, because if they're not granted, there's no point in even starting a new thread to perform the task, because it's not going to be able to do anything anyway.

Share this post


Link to post

That's not my case... I can download a file regardless of whether i can save in external storage. I can save in private storage, which is fine for the app. I just prefer the shared downloads folder to have better visibility outside the app of the downloaded file.

Share this post


Link to post

I decided to follow your advice, and to call requestPermissions only from the main UI thread. I've been running my app for several hours today and the odd errors and debugger stepping into assembly code seems to have stopped. So maybe that's why I've been having some problems lately. Thanks for the feedback.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×