Strange behaviour in Android app when running as service

Android app cant call any service method when running as a service

definition (i check this code runs ok in the service)

method DataAccess.doInitComponents();
begin
  try
    self.readPreferences();
    self.loadBriefcase;

    if (aesEnvelope = nil) then
    begin
      aesEnvelope := new AesEncryptionEnvelope(adapter_aesPassword);
      aesEnvelope.Enabled := true;
      android.util.Log.i(TAG, 'DataAccess.doInitComponents created envelope');
    end;

    if (fRemoteDataAdapter = nil) then
    begin
      fRemoteDataAdapter := new RemoteDataAdapter(java.net.URI.&create(adapter_serverUrl), adapter_dataService, adapter_loginService);
      fRemoteDataAdapter.Message.Envelopes.put('AES', aesEnvelope);
      fRemoteDataAdapter.DynamicSelect := true;
      HttpClientChannel(fRemoteDataAdapter.ClientChannel).Timeout := 5000;
      android.util.Log.i(TAG, 'DataAccess.doInitComponents create fRemoteDataAdapter');
    end;

    // 20/09/2017 creo data service
    if (fDataService = nil) then
    begin
      android.util.Log.i(TAG, 'NewLibrary.DataService_Proxy adapter_serverUrl ' + adapter_serverUrl);
      fDataService := new NewLibrary.DataService_Proxy(java.net.URI.&create(adapter_serverUrl));
      //(fDataService.ProxyMessage as BinMessage).UseCompression       := true;
      (fDataService.ProxyClientChannel as HttpClientChannel).Timeout := 5000;
      (fDataService.ProxyMessage as BinMessage).Envelopes.put('AES', aesEnvelope);
       fDataService.ProxyClientChannel.ChannelCallback := new interface ClientChannel.IClientChannelCallback(
        clientChannelNeedsLogin := method(anException: Exception)
        begin
          android.util.Log.i(TAG, 'DataAccess.doInitComponents SessionNotFoundException was thrown');
          System.out.println("SessionNotFoundException was thrown");
          exit true;
        end,
        requestFailWithException := method(anException: Exception)
        begin
          android.util.Log.i(TAG, 'DataService requestFailWithException ' + anException.Message);
          doMessageShow('DataService requestFailWithException ' + anException.Message, false);
          System.out.println(anException.Message);
        end
      );
      android.util.Log.i(TAG, 'DataAccess.doInitComponents created fDataService');
    end;
  except
    on e: Exception do
    begin
      doMessageShow('DataModule.diInitComponents error ' + e.Message, false);
    end
  end;
  android.util.Log.i(TAG, 'DataAccess.doInitComponents end');
end;

call to service method

 try
   ServerDateTime := fDataService.getDateTime(aVersionCode);
   aDateTimeProvider := TProveedorFecha.TProveedorFecha_Servidor;
   result := True;
  except
    on e: Exception do
    begin
      doMessageShow('Can´t contact server.' + e.Message, false);
    end;
  end;

returns this error message

Can´t contact server. string arg == null

Same problem when trying to applyupdates to briefcase.

  try
    self.fRemoteDataAdapter.applyChanges(self.data.fBitacoraEntidad);
    enviook := true;
  except
    on e: Exception do
    begin
      doMessageShow('Trying to send Briefcase error :'+ e.Message, true);
    end;
  end;

e.Message show no text

Trying to send Briefcase error:

As i say, when running the app when an activity it runs ok but when running in background as a service the only thing dont work is send briefcase and calling server. Even Internet check works fine.

Best regards.

Could you also provide exception stacktraces?

Thanks in advance

It happens only when run as a service. Have no idea how to takes stack traces(?). Of you explain me how i will provide this.

F.e. something like this should work:

...
on e: Exception do begin
  var writer := new java.io.StringWriter();
  var printWriter := new java.io.PrintWriter(writer);
  e.printStackTrace(printWriter);
  printWriter.flush();

  var stackTrace := e.Message + " --  " + writer.toString();
  doMessageShow(stackTrace, true);
end;

…

Here is

ServerDateTime := fDataService.getDateTime(aVersionCode);

Can´t contact server.string arg == null --  java.lang.NullPointerException: string arg == null
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at java.lang.String.concat(Native Method)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.genartech.peopletracker.DataAccess.$doInitComponents$b__1(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas:252)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.genartech.peopletracker.DataAccess$4.requestFailWithException(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.remobjects.sdk.ClientChannel.triggerFailWithException()
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.remobjects.sdk.ClientChannel.dispatch()
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at newlibrary.DataService_Proxy.getDateTime(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/NewLibrary_Intf.pas:486)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.genartech.peopletracker.DataAccess.dogetServerDateTime(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas:416)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.genartech.peopletracker.DataAccess.doGetBestDateTime(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas:449)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.genartech.peopletracker.DataAccess.$doInitGPS$b__0(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas:1035)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.genartech.peopletracker.DataAccess$5.onLocationResult(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.google.android.gms.internal.zzcdf.zzq(Unknown Source)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.google.android.gms.internal.zzbdw.zzb(Unknown Source)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.google.android.gms.internal.zzbdx.handleMessage(Unknown Source)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at android.os.Handler.dispatchMessage(Handler.java:102)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at android.os.Looper.loop(Looper.java:150)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at android.app.ActivityThread.main(ActivityThread.java:5621)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at java.lang.reflect.Method.invoke(Native Method)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
07-05 14:57:19.517 I/PeopleTrackerService(13297): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)
android.os.NetworkOnMainThreadException
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1285)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at java.net.InetAddress.lookupHostByName(InetAddress.java:431)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at java.net.InetAddress.getAllByName(InetAddress.java:215)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:358)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:331)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:249)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:437)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:245)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.remobjects.sdk.HttpClientWorker.Dispatch()
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.remobjects.sdk.HttpClientChannel.internalDispatch()
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.remobjects.sdk.ClientChannel.dispatch()
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.remobjects.dataabstract.intf.DataAbstractService_Proxy.UpdateData()
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.remobjects.dataabstract.RemoteDataAdapter.internalUpdate()
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.remobjects.dataabstract.RemoteDataAdapter.applyChanges()
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.remobjects.dataabstract.RemoteDataAdapter.applyChanges()
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.genartech.peopletracker.DataAccess.doInitorEndTask(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas:728)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.genartech.peopletracker.DataAccess.$doInitGPS$b__0(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas:1043)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.genartech.peopletracker.DataAccess$5.onLocationResult(/Volumes/Work/Sistemas/EnterpriseServices/Shared/PeopleTrackerService/com.genartech.peopletracker/DataAccess.pas)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.google.android.gms.internal.zzcdf.zzq(Unknown Source)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.google.android.gms.internal.zzbdw.zzb(Unknown Source)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.google.android.gms.internal.zzbdx.handleMessage(Unknown Source)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at android.os.Handler.dispatchMessage(Handler.java:102)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at android.os.Looper.loop(Looper.java:150)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at android.app.ActivityThread.main(ActivityThread.java:5621)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at java.lang.reflect.Method.invoke(Native Method)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
07-05 15:24:44.907 I/PeopleTrackerService(19717): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)

that pretty much explains it, right? Apparently you’re not allowed to make network requests on Main, you need to use a different thread. Could be.

1 Like

Please read this blog: Why Ice Cream Sandwich Crashes your App | Android Design Patterns

As for the first exception - please double-check that the server Url is assigned to the channel.

2 Likes

Im sorry but no, i dont get it.

When the app is running like a normal app im caling the same code after a button click, no async call at all. I bet is in the MAIN or UI thread. And works perfect!

Then, when running as a service it fails. I read the document, understand the idea, but still dont see how can that work without any special async call code, just a simple call on the main thread (or UI thread as the document name) but dont work when running in background as a service? If remobjects is implementing internally some async call i have no idea. In any case still dont explain why called from main UI thread it works.

Best regards.

The code is executed at initialization

if (fDataService = nil) then
    begin
      android.util.Log.i(TAG, 'NewLibrary.DataService_Proxy adapter_serverUrl ' + adapter_serverUrl);
      fDataService := new NewLibrary.DataService_Proxy(java.net.URI.&create(adapter_serverUrl));
      (fDataService.ProxyClientChannel as HttpClientChannel).Timeout := 5000;
      (fDataService.ProxyMessage as BinMessage).Envelopes.put('AES', aesEnvelope);
       fDataService.ProxyClientChannel.ChannelCallback := new interface ClientChannel.IClientChannelCallback(
        clientChannelNeedsLogin := method(anException: Exception)
        begin
          android.util.Log.i(TAG, 'DataAccess.doInitComponents SessionNotFoundException was thrown');
          System.out.println("SessionNotFoundException was thrown");
          exit true;
        end,
        requestFailWithException := method(anException: Exception)
        begin
          android.util.Log.i(TAG, 'DataService requestFailWithException ' + anException.Message);
          doMessageShow('DataService requestFailWithException ' + anException.Message, false);
          System.out.println(anException.Message);
        end
      );
      android.util.Log.i(TAG, 'DataAccess.doInitComponents created fDataService');
    end;

but cant find a property like channel for fDataService to see if the url is still there . Any suggestion?

P.S. As i say that code works fine when the app is manually launched, only dont work when is launched for the OS.

Could you change this code

    ...
    requestFailWithException := method(anException: Exception)
    begin
      android.util.Log.i(TAG, 'DataService requestFailWithException ' + anException.Message);
      doMessageShow('DataService requestFailWithException ' + anException.Message, false);
      System.out.println(anException.Message);
    end
    ...

so it will first check that anException.Message is not null and only after that perform the rest of the logging using its value? It could be that the original exception is hidden behind another one.

F.e. you could try to use the following code:

  var message := coalesce(anException.Message, exception.Class.TypeName);
1 Like

The problem is the call in the main thread as @mh and you pointed. I already solved the aplly updates problem putting the call in an async task. Just need to solve the getTime in the same way i think.

Still not get why it works as an standard app… Anyway, thanks a lot to both for the amazing help!

Best regards.