Jump to content
Yaron

My android app restarts on permission request

Recommended Posts

I am trying to save an image to the photo gallery using Delphi 10.3 and Android 6+

 

However, when the user accepts the access request prompt on the very first call, my entire app restarts all on it's own, is there any way to disable this behavior so my app doesn't restart?

 

 

I implemented the code based on this blog post:

http://blong.com/Articles/AndroidPermissions/DelphiAppPermissions.htm

 

After calling (on form create):

  FPermission_READ_EXTERNAL_STORAGE  := JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE);
  FPermission_WRITE_EXTERNAL_STORAGE := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);

 

I am calling this code to show the prompt and save the image:

      // Request permission
      PermissionsService.RequestPermissions([FPermission_WRITE_EXTERNAL_STORAGE, FPermission_READ_EXTERNAL_STORAGE],
        procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
        begin
          if (Length(AGrantResults) = 2) and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) then
          Begin
            { Save file }
            BaseFolder := System.IOUtils.TPath.GetSharedPicturesPath;
            If DirectoryExists(BaseFolder) = True then
            Begin
              PIKAFolder := BaseFolder+System.IOUtils.TPath.DirectorySeparatorChar+clientGameName;
              If DirectoryExists(PIKAFolder) = False then ForceDirectories(PIKAFolder);

              PIKAFile := PIKAFolder+System.IOUtils.TPath.DirectorySeparatorChar+clientGameName+'_'+ReplaceStr(ReplaceStr(DateTimeToStr(Now),':','.'),'/','.')+saveImageFileExt;
              Try
                MyImage.SaveToFile(PIKAFile);
              Except
                clientFadingMessage := strErrorSavingPicture;
              End;
              If FileExists(PIKAFile) = True then clientFadingMessage := strPictureSaved else If clientFadingMessage = '' then clientFadingMessage := strErrorSavingPicture2;
            End
            Else clientFadingMessage := strPictureFolderNotFound;
          End
            else
          begin
            clientFadingMessage := strErrorSavingPicture;
          end;
        end
      );

 

Share this post


Link to post

Have you traced through the code to see where it fails? Does it reach the first line in the anonymous method?

Share this post


Link to post

Is there a risk that ForceDirectories can fail with an exception?

/offtopic: Comparisons with boolean values make me cringe.

Share this post


Link to post

@Dave Nottage

I can't really debug since I constantly suffer from the "Unable to start gdbserver on port '64311'. Port is already in use.", so instead I've added many more debug output lines.

 

I finally figured out what was going on, I was creating my bitmap inside a function that was triggered by a timage-clicked, that function then called the permission request with an anonymous function.

However, once the anonymous function was triggered, the bitmap var was no longer valid.

I fixed the issue by creating the bitmap within the anonymous function.

 

Share this post


Link to post
11 hours ago, Lars Fosdal said:

Is there a risk that ForceDirectories can fail with an exception?

It shouldn't.  It has a Boolean return value, it should just return False on failure.

 

@Yaron the code you have showed can be simplified a little bit:

// Request permission
PermissionsService.RequestPermissions(
  [FPermission_WRITE_EXTERNAL_STORAGE, FPermission_READ_EXTERNAL_STORAGE],
  procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
  var
    fmt: TFormatSettings;
  begin
    if (Length(AGrantResults) = 2) and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) then
    begin
      { Save file }
      PIKAFolder := System.IOUtils.TPath.GetSharedPicturesPath;
      if PIKAFolder <> '' then PIKAFolder := TPath.Combine(PIKAFolder, clientGameName);        

      if ForceDirectories(PIKAFolder) then
      begin
        fmt := TFormatSettings.Create;
        fmt.DateSeparator := '.';
        fmt.TimeSeparator := '.';

        PIKAFile := TPath.Combine(PIKAFolder, clientGameName + '_' + DateTimeToStr(Now, fmt) + saveImageFileExt);
        try
          MyImage.SaveToFile(PIKAFile);
          clientFadingMessage := strPictureSaved;
        except
          clientFadingMessage := strErrorSavingPicture;
        end;
      end
      else
        clientFadingMessage := strPictureFolderNotFound;
    end
    else
      clientFadingMessage := strErrorSavingPicture;
  end
);

 

Share this post


Link to post
10 hours ago, Lars Fosdal said:

Actually, http://docwiki.embarcadero.com/CodeExamples/Rio/en/DirListBoxUpdate_(C%2B%2B) says

Quote

Note: A EInOutError occurs if you add a directory that already exists. You must also add the new directory to your current directory.

and a look at it in the source code verifies it.

Last time I checked, ForceDirectories() DOES NOT raise an exception if the specified directory already exists.  Are you sure the documentation you quoted is referring to ForeceDirectories() and not TDirListBox?  Which source code did you "verify" exactly?

 

The ForceDirectories() documentation does warn against calling it with a blank string, which I accidentally did in my example above if TPath.GetSharedPicturePath() returns a blank string.

Edited by Remy Lebeau

Share this post


Link to post

function SelectDirectory calls ForceDirectories, and there is no raise in the TDirectoryListBox class.

 

Anyways - ForceDirectories can cause an exception under the specified circumstances - so the real question is: What is the content of PIKAFolder when it is passed to ForceDirectories, and - if not blank - what happens if the folder already exists?

 

Share this post


Link to post
15 hours ago, Lars Fosdal said:

Anyways - ForceDirectories can cause an exception under the specified circumstances

Which circumstances exactly?

15 hours ago, Lars Fosdal said:

if not blank - what happens if the folder already exists?

ForceDirectories() SHOULD succeed without error in that case.  Its job is to ensure a path exists, not to report an error if it does exist.  The only time it should ever raise an exception is if the input path is blank.  Anything else should cause it to simply return True if the path already exists or was successfully created, or False otherwise.  If it is not working that way, that is a bug for Embarcadero to fix. 

 

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

×