Are the Delphi services unfeasible for real applications? :(

Are the Delphi services unfeasible for real applications? :(

I really don't know what can be happening. My code is far simple, it gets info from the GPS via JNI structure, opens an connection to a remote database and that's all.
I tried to isolate every main routine, but the GPS because it is mandatory. At first the application got a weird error that occurs just after few iterations (about 3 to 6 min running) and I post about it here, after create a new project everything was apparently ok, but the error is still there, now it take a longer, about 30 min to several hours and will crash the same way, with a non specific cause, error line whatever: Class aborted (6)

As Roland Kossow suggests, could be a memory error. But I am using an application called "SystemPanel" where I can watch its behavior, including the resident memory, shared and effective memory, cpu usage and I don't see memory leaks or cpu overload. BUT, when the app crashes I cannot sometimes even stop it, because it consume almost all cpu cicles :( very very bad.

Important and I will rewrite: the application won't crash immediately, it can take from some minutes (30 or more) to a lot of hours.

Original post: https://plus.google.com/+MagnoLima/posts/4QZwiDHxV9h

Comments

  1. Hi - sorry to read that your problem persists.

    I now found this thread ...
    community.embarcadero.com - Location Sensor in background Service on Android (1/1) - - Embarcadero Community

    Could this help?

    It says there "Remember to not use FMX components in services - only if there is written in help that it can by used."
    Since I still do not have a good enough understanding of your code - could this cause the problem?

    Do you use this LocationListenerService thingy here ...
    https://developer.android.com/reference/android/location/LocationListener.html
    ... ?

    See also ...
    https://forums.embarcadero.com/thread.jspa?messageID=715293

    Markus Humm writes there: "afaik you cannot use FMX stuff in Android services. You have to look
    inside TLocation in order to find out how the ANdroid specific
    implementation is done using the Android Java style/based API via the Java bridge Delphi uses."

    ReplyDelete
  2. Still having not a very good understanding of your solution, this looks relevant also - there seem to be general issues with Android Services and GPS which need to be taken care of. ...
    stackoverflow.com - Get GPS location via a service in Android

    ReplyDelete
  3. Roland Kossow I am very glad for all your effort in helping me! Well, for sure I know FMX cannot be used and I am not.

    I will read the links and mainly the last post on StackOverflow :)

    Bellow the GPS routine I am using:
    type
    TLocationListener = class;
    TDM = class(TAndroidService) ... blah blah..
    ...
    public
    procedure onLocationChanged(Location: JLocation);
    end;

    TLocationListener = class(TJavaLocal, JLocationListener)
    private
    [weak]
    FParent: TDM;
    public
    constructor Create(AParent: TDM);
    procedure onLocationChanged(Location: JLocation); cdecl;
    procedure onProviderDisabled(provider: JString); cdecl;
    procedure onProviderEnabled(provider: JString); cdecl;
    procedure onStatusChanged(provider: JString; status: Integer; extras: JBundle); cdecl;
    end;

    //** the AndroidServiceCreate() proc
    procedure AndroidServiceCreate();
    begin
    ...blah blah...
    if not Assigned(FLocationManager) then
    begin
    LocationManagerService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.LOCATION_SERVICE);
    FLocationManager := TJLocationManager.Wrap((LocationManagerService as ILocalObject).GetObjectID);
    if not Assigned(locationListener) then
    locationListener := TLocationListener.Create(Self);
    FLocationManager.requestLocationUpdates(TJLocationManager.JavaClass.GPS_PROVIDER, 10000, 10, locationListener, TJLooper.JavaClass.getMainLooper);
    end;

    Location := FLocationManager.getLastKnownLocation(TJLocationManager.JavaClass.GPS_PROVIDER);
    onLocationChanged(Location);
    end;
    //**

    constructor TLocationListener.Create(AParent: TDM);
    begin
    inherited Create;
    FParent := AParent;
    end;

    procedure TLocationListener.onLocationChanged(Location: JLocation);
    begin
    FParent.onLocationChanged(Location);
    end;

    // * here I get the info I need (shorted code here)
    procedure TDM.onLocationChanged(Location: JLocation);
    begin
    FLongitude := Location.getLongitude;
    FLatitude := Location.getLatitude;
    FAltitude := Location.getAltitude;
    FSpeed := Location.getSpeed;
    FBearing := Location.getBearing;
    ... etc
    end;

    ReplyDelete
  4. did you logcat the issue? is that possible? Could it be that a null value is passed after some time for unknown reasons in onlocationchanged after the getlastknownlocation call? could you check if Location is assigned and only call onlocationchanged if it is.

    ReplyDelete
  5. I've implemented the logcat, but now I will trace this to check in case of invalid coordinates and let you know!

    ReplyDelete
  6. Bad coordinates would provably be no problem, but NULL. Because then Onlocationchanged will throw an exception when accessing getLatitude.

    ReplyDelete
  7. Attila Kovacs There is and it IMO should be made use of in the above code.

    ReplyDelete
  8. To be more specific ....
    Magno Lima could you check if the following modification results in a more robust background service?
    Or is there anything I am not aware of, that does not allow the code below?

    [...]
    // * here I get the info I need (shorted code here)
    procedure TDM.onLocationChanged(Location: JLocation);
    begin
    if not Assigned(Location) then Exit;
    try
    FLongitude := Location.getLongitude;
    FLatitude := Location.getLatitude;
    FAltitude := Location.getAltitude;
    FSpeed := Location.getSpeed;
    FBearing := Location.getBearing;
    ... etc
    except
    //Log the Error
    end;
    end;
    [...]

    ReplyDelete
  9. Roland Kossow I just put your suggestion, right now it is running, lets see if we can catch the issue.

    ReplyDelete
  10. Other test I am also doing is "Location.getLatitude.IsNan", but I am not sure how Delphi will handle that, because IsNan should catch is the float is Not a number, such invalid chars or even nulls.

    ReplyDelete
  11. What's the reason for implementing your own class that uses JLocationListener? You should be able to use TLocationSensor in an Android service, as it does not use FMX units. Regardless, I'd make liberal use of log statements (and the Monitor app, or similar) to discover where the problem lies. I've implemented cross-platform logging that does not require FMX, in the KastriFree project (check the Core folder):

    github.com - DelphiWorlds/KastriFree

    ReplyDelete
  12. David Nottage I am not sure about that. Simply putting the units for Location will crash the app as some other unit will be used and I am not telling that I am get the component from the palette but creating it in runtime. Am I missing something else? A lot of people says TLocation will NOT work with Android Services and that solution is what I use. Btw thanks for the link, I will check it for sure and I had put toons of logcat but so far I was unable to determine where the the app crashes.

    ReplyDelete
  13. I expect that it boils down to the same issue: that the RTL code is attempting to access the NativeActivity, which is nil in a service, at least for Delphi apps. I'll have a deeper look into it in a few hours.

    ReplyDelete
  14. Hello,

    Could you try this code ?

    function TLocationServiceModule.AndroidServiceStartCommand(const Sender: TObject;
    const Intent: JIntent; Flags, StartId: Integer): Integer;
    begin
    Result := TJService.JavaClass.START_STICKY;
    TThread.CreateAnonymousThread(procedure ()
    begin
    InitializeLocationSensor;
    end).Start;
    end;

    procedure TLocationServiceModule.InitializeLocationSensor
    begin
    // java intrface solution here
    end;

    ReplyDelete
  15. Tomasz Andrzejewski Right now compiling with your code. My original code use to initialize the LocationSensor at OnCreate() of TDM. Now I moved to StartServiceCommand() and let's see how it works.

    ReplyDelete
  16. OK.. I'll hold off on doing anything :-)

    ReplyDelete
  17. David Nottage Tomasz Andrzejewski Roland Kossow well guys, so far so GOOD! The good is that now the app service is damn more stable! :) :) The logcat is working like a precise clock. The bad here is that I don't really know what tech really made the job, the Tomasz's solution much probably, but I am not sure. I will let the app running for a very long period (more the 24h) and if nothing weird happens I let you know. Ok, if something goes bad I post here.
    I walked outside home for some hours and returned, plug the phone on USB and kept watching the log (using the kbmLogCat software). Also the data is sending to the server side perfectly, as it should, keeping info and protections when no GPS or GRPS data network is available.
    Thank for very much for such precious help! :) I hope it keeps stable.

    ReplyDelete
  18. Magno Lima Great to hear! I'll be using the findings here for my own projects; thanks

    ReplyDelete
  19. Great. Let us informed about your progress

    ReplyDelete
  20. Tomasz Andrzejewski So far it is working very fine! I will post on my blog the a very simple sample later with the code, so someone could use and improve it.

    ReplyDelete

Post a Comment