Jump to content
Sign in to follow this  
3delite

Delphi Alexandria 11.1 Android AAB from Play Store exits on startup

Recommended Posts

Posted (edited)

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
Posted (edited)

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
Posted (edited)

@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

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
Sign in to follow this  

×