Jump to content
3delite

Delphi Alexandria 11.1 Android AAB from Play Store exits on startup

Recommended Posts

Hi!

 

Android app. seems working fine in debug or release (Development) mode on my Android device. But if I upload the AAB file to Google Play Store and install it from there it exits on startup. Not sure if it's a crash I have very little experience with Android.
The project is from the XE5 era.

 

Tried:

- Deleted the manifest file, so it was re-created by Delphi
- Did a "Revert system files to default"

- Did a "Revert to default" in Deployment

 

Google Play Store page: https://play.google.com/store/apps/details?id=com.embarcadero.MP4StreamEditorClient

 

As I wrote it seems working fine if I start it through Delphi+USB and also if I start it after it has been installed by Delphi, just the Install and start from Play Store does not work.

 

Any ideas?

 

Thank you!
3delite

Edited by 3delite

Share this post


Link to post

Hi, what you could try is making a new FMX-application and after that add all the units of the old dpk to the new dpk. EMB have added a lot of config to the dproj which isn't (of at least wasn't till 10.4.2) automatically added when you upgrade to a newer Delphi-version.

I know you'll have to set a lot of config again, but give it a try at least.

Share this post


Link to post
12 hours ago, 3delite said:

install it from there it exits on startup

For me, it asked for permissions (which I granted), then restarts over and over, presenting a toast related to permissions being granted.

 

Without knowing exactly the code is doing during startup, it's going to be difficult to diagnose. I suggest moving as much code as you can out of FormCreate (if you use that event) or the main forms constructor (if you have overridden it), and call it later.

Share this post


Link to post
39 minutes ago, Pieter Bas Hofstede said:

Hi, what you could try is making a new FMX-application and after that add all the units of the old dpk to the new dpk. EMB have added a lot of config to the dproj which isn't (of at least wasn't till 10.4.2) automatically added when you upgrade to a newer Delphi-version.

I know you'll have to set a lot of config again, but give it a try at least.

I've even had a situation at one day of an existing project, delete dproj+everything but keep the dpk, when opening the dpk Delphi generated a different dproj+deployment comparing to a complete new FMX-application-setup. Please be aware of that.

Share this post


Link to post

Thank you very much for the suggestions!

 

It came to my mind that, as the permission request is called, it is in FormCreate(), so the code does get there.

I have this in FormCreate() after that:

 

        if NOT LoadBASS then begin
            //Showmessage('Error loading BASS.');
            Halt;
        end;

 

And LoadBASS is:

 

function LoadBASS: Boolean;
var
    DocDir: string;
    BASSLibraryHandle: THandle;
    BASSMixLibraryHandle: THandle;
    BASSFXLibraryHandle: THandle;
begin
    Result := False;
    DocDir := IncludeTrailingPathDelimiter(System.IOUtils.TPath.GetLibraryPath);
    //* BASS
    BASSLibraryHandle := LoadLibrary(PChar(DocDir + 'libbass.so'));
    if BASSLibraryHandle = 0 then begin
        Exit;
    end;
    if BASSLibraryHandle <> 0 then begin
        @BASS_Init := GetProcAddress(BASSLibraryHandle, ('BASS_Init'));
        @BASS_StreamCreateFile := GetProcAddress(BASSLibraryHandle, ('BASS_StreamCreateFile'));
        @BASS_ChannelPlay := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelPlay'));
        @BASS_ErrorGetCode:=GetProcAddress(BASSLibraryHandle, ('BASS_ErrorGetCode'));
        @BASS_Free:=GetProcAddress(BASSLibraryHandle, ('BASS_Free'));
        @BASS_GetCPU:=GetProcAddress(BASSLibraryHandle, ('BASS_GetCPU'));
        @BASS_SetConfig:=GetProcAddress(BASSLibraryHandle, ('BASS_SetConfig'));
        @BASS_GetConfig:=GetProcAddress(BASSLibraryHandle, ('BASS_GetConfig'));
        @BASS_GetDevice:=GetProcAddress(BASSLibraryHandle, ('BASS_GetDevice'));
        @BASS_ChannelGetInfo:=GetProcAddress(BASSLibraryHandle, ('BASS_ChannelGetInfo'));
        @BASS_MusicLoad := GetProcAddress(BASSLibraryHandle, ('BASS_MusicLoad'));
        @BASS_MusicFree := GetProcAddress(BASSLibraryHandle, ('BASS_MusicFree'));
        @BASS_StreamFree := GetProcAddress(BASSLibraryHandle, ('BASS_StreamFree'));
        @BASS_ChannelBytes2Seconds := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelBytes2Seconds'));
        @BASS_ChannelGetLength := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelGetLength'));
        @BASS_ChannelGetPosition := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelGetPosition'));
        @BASS_ChannelStop := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelStop'));
        @BASS_ChannelPause := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelPause'));
        @BASS_PluginLoad := GetProcAddress(BASSLibraryHandle, ('BASS_PluginLoad'));
        @BASS_ChannelSetSync := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelSetSync'));
        @BASS_GetDeviceInfo := GetProcAddress(BASSLibraryHandle, ('BASS_GetDeviceInfo'));
        @BASS_ChannelSetPosition := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelSetPosition'));
        @BASS_ChannelRemoveSync := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelRemoveSync'));
        @BASS_ChannelSeconds2Bytes := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelSeconds2Bytes'));
        @BASS_ChannelLock := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelLock'));
        @BASS_StreamCreateURL := GetProcAddress(BASSLibraryHandle, ('BASS_StreamCreateURL'));
        @BASS_Stop := GetProcAddress(BASSLibraryHandle, ('BASS_Stop'));
        @BASS_ChannelGetTags := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelGetTags'));
        @BASS_ChannelSetFX := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelSetFX'));
        @BASS_ChannelRemoveFX := GetProcAddress(BASSLibraryHandle, ('BASS_ChannelRemoveFX'));
        @BASS_FXSetParameters := GetProcAddress(BASSLibraryHandle, ('BASS_FXSetParameters'));
        @BASS_FXGetParameters := GetProcAddress(BASSLibraryHandle, ('BASS_FXGetParameters'));
        Result := True;
    end;
    //* BASSMix
    BASSMixLibraryHandle := 0;
    if FileExists(DocDir + 'libbassmix.so') then begin
        BASSMixLibraryHandle := LoadLibrary(PChar(DocDir + 'libbassmix.so'));
        if BASSMixLibraryHandle = 0 then begin
            Exit;
        end;
    end else begin
        Showmessage('Error loading: ' + DocDir + 'libbassmix.so');
    end;
    if BASSMixLibraryHandle <> 0 then begin
        @BASS_Mixer_StreamCreate := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_StreamCreate'));
        @BASS_Mixer_StreamAddChannel := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_StreamAddChannel'));
        @BASS_Mixer_ChannelFlags := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelFlags'));
        @BASS_Mixer_ChannelSetPosition := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelSetPosition'));
        @BASS_Mixer_ChannelGetPosition := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelGetPosition'));
        @BASS_Mixer_ChannelGetData := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelGetData'));
        @BASS_Mixer_ChannelSetSync := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelSetSync'));
        @BASS_Mixer_ChannelRemoveSync := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelRemoveSync'));
        @BASS_Mixer_ChannelSetMatrix := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelSetMatrix'));
        @BASS_Mixer_ChannelSetEnvelope := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelSetEnvelope'));
        @BASS_Mixer_ChannelRemove := GetProcAddress(BASSMixLibraryHandle, ('BASS_Mixer_ChannelRemove'));
        Result := True;
    end;
    //* BASS_FX
    BASSFXLibraryHandle := LoadLibrary(PChar(DocDir + 'libbass_fx.so'));
    if BASSFXLibraryHandle = 0 then begin
        Exit;
    end;
    if BASSFXLibraryHandle <> 0 then begin
        @BASS_FX_GetVersion := GetProcAddress(BASSFXLibraryHandle, ('BASS_FX_GetVersion'));
        BASS_FX_GetVersion;
        Result := True;
    end;
end;

 

Could it be possible that the folder is invalid? The needed SO files are in "library\lib\arm64-v8a\" and this is not existing when using an AAB?

 

DocDir := IncludeTrailingPathDelimiter(System.IOUtils.TPath.GetLibraryPath);

Attached a screenshot of the deplyment page.

 

Does the AAB format change the folder structure in some way?

Untitled-1.png

Share this post


Link to post

 

4 hours ago, 3delite said:

Does the AAB format change the folder structure in some way?

Whatever the case, the BASS libraries are not ending up in the app. I "pulled" the APK after installing the app, and there's no lib folder:

 

image.thumb.png.068072c05604ee636bd0ccfaf48083d5.png

 

Share this post


Link to post

That's strange! Managed to fix it though. The BASS .so files were not found with the TPath.GetLibraryPath function. While Googleing for this issue there seems to be some kind of new system for loading the .so files and the solution is to simply not specify a path for the LoadLibrary() call, the Android system picks the needed folder.

So just use:

 

BASSLibraryHandle := LoadLibrary(PChar('libbass.so'));

This now seems working perfectly for both .apk and .aab. This goes for all the .so files that are loaded with LoadLibrary().

And in deployment the .so files are all remote path "library\lib\arm64-v8a\" (same as before for 64 bit).

 

Thank you very much for helping! If it would be possible to check once again the install from Google Play Store (I updated the package, that seems working fine here now)?

 

Thank you!

3delite

Edited by 3delite
  • Like 1

Share this post


Link to post

@3delite 

Loading dynamic libraries on Android is not that trivial, you will still have problems on some devices of some manufacturers. Here are 3 main tips:

 

1) Filename: ALWAYS suffix "lib", like "libbass.so"

 

2) Deployment:

  • On 32bit, the remote path "library\lib\armeabi-v7a\"
  • On 64bit, the remote path "library\lib\arm64-v8a\"
  • Also on 64bit, add the 32bit binary with the remote path "library\lib\armeabi-v7a\" and the condition "'$(AndroidAppBundle)''==''true'" (with the quotes). The condition you can only change via ToolsApi or manually in .dproj.

See how we do it: https://github.com/skia4delphi/skia4delphi/blob/eed4afbf8a34137a9bfa308bcb5ef87cee84abcb/Source/VCL/Designtime/Skia.Vcl.Designtime.ProjectMenu.pas#L219-L221

 

3) Loading:
First try to load using only the filename, and in case of failure use the library path + filename.
See how we do it: https://github.com/skia4delphi/skia4delphi/blob/eed4afbf8a34137a9bfa308bcb5ef87cee84abcb/Source/Skia.API.pas#L2119-L2124

 

 

Edited by vfbb

Share this post


Link to post

Thank you very much for the detailed tips!

 

Ok, so I changed the code to:

 

    BASSLibraryHandle := LoadLibrary(PChar('libbass.so'));
    if BASSLibraryHandle = 0 then begin
        BASSLibraryHandle := SafeLoadLibrary(TPath.Combine(TPath.GetLibraryPath, 'libbass.so'));
        if BASSLibraryHandle = 0 then begin
            Showmessage('Error loading libbass.so.');
            Exit;
        end;
    end;
    if BASSLibraryHandle <> 0 then begin
        @BASS_Init := GetProcAddress(BASSLibraryHandle, ('BASS_Init'));
        ...

BTW. I downloaded the Skia4Delphi package a couple of weeks ago, seems very cool stuff. I did not have time to check it though, but seems professional.

 

Thank you very much for helping with this issue!

 

  • Like 1

Share this post


Link to post
On 6/6/2022 at 1:44 PM, vfbb said:

2) Deployment:

  • On 32bit, the remote path "library\lib\armeabi-v7a\"
  • On 64bit, the remote path "library\lib\arm64-v8a\"
  • Also on 64bit, add the 32bit binary with the remote path "library\lib\armeabi-v7a\" and the condition "'$(AndroidAppBundle)''==''true'" (with the quotes). The condition you can only change via ToolsApi or manually in .dproj.

See how we do it: https://github.com/skia4delphi/skia4delphi/blob/eed4afbf8a34137a9bfa308bcb5ef87cee84abcb/Source/VCL/Designtime/Skia.Vcl.Designtime.ProjectMenu.pas#L219-L221

 

 

I also struggle to load a .so. In my case the .so was created in Delphi for testing purposes. I tried to follow your idea with the deployment but I didn't fully understand this yet.

Is this only relevant if I'm building an .aab later on?

I'm currently still struggeling with a normal apk / debugger / debug build.
I'm currently using an Android 11 device but will test on a Android 13 device in a few minutes. On the device used the first call to SafeLoadLibrary results in a Segmentation fault(11) crash.
Here's my code:

procedure Tf_Main.b_CalcClick(Sender: TObject);
var
  Handle : HMODULE;
  s : string;
begin
  Memo1.Lines.Clear;

  s := TPath.Combine(TPath.GetLibraryPath, 'libSO_Test.so');
  if System.SysUtils.FileExists(s) then
    Memo1.Lines.Add('Exists');

  Handle := SafeLoadLibrary('libSO_Test.so');
  Memo1.Lines.Add('Handle1: ' + Handle.ToString);
  if (Handle = 0) then
    Handle := SafeLoadLibrary(s);

  Memo1.Lines.Add('Handle2: ' + Handle.ToString);

  if (Handle <> 0) then
  begin
    try
      FDoAdd := GetProcAddress(Handle, PChar('DoAdd'));

      if (@FDoAdd = nil) then
          Memo1.Lines.Add('Failure loading proc (is nil)')
      else
      begin
        l_Result.Text := FDoAdd(tf_Summand1.Text.ToInteger,
                                tf_Summand2.Text.ToInteger).ToString;
        FDoAdd := nil;
        Memo1.Lines.Add('Success');
      end;
    finally
      FreeLibrary(Handle);
    end;
  end
  else
    Memo1.Lines.Add('SO handle is invalid');
end;

Any idea?

Share this post


Link to post
10 hours ago, TurboMagic said:

I tried to follow your idea with the deployment but I didn't fully understand this yet.

Is this only relevant if I'm building an .aab later on?

Yes, this is relevant only for the .aab generation. Note: you can’t change the ‘condition’ on IDE side, you should open the dproj and add it manually. See one dproj with that:
https://github.com/skia4delphi/skia4delphi/blob/eed4afbf8a34137a9bfa308bcb5ef87cee84abcb/Samples/Demo/FMX/Projects/RAD%20Studio%2011%20Alexandria/Skia4Delphi.dproj#L1182

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

×