Android Question [SOLVED] Service stays in Service_Start

lemonisdead

Well-Known Member
Licensed User
Longtime User
Hello,
I was making some debugging on an existing app after a bug report for an app that was not... working well...
In fact, I had to admit that a service stayed in Service_Start if it was restarted after the whole app had been killed (via a task killer or manually by swiping the activity from the recent apps).

So, I made the simplest skeleton, including the main method I did use, logging the information I thought could block but I still don't understand why the second service enters Service_Start but stops there.

Here is how it works : the main activity is only responsible of updating its content from a list, using a resumable sub.
The Starter service starts a sv1 service which starts a sv2 service.
When the app is killed, Starter schedules the sv1 service again.

So to reproduce the behavior, just execute the app once. Then kill it by swiping its activity. sv1 is restarted, sv2 is restarted. While sv1 seems to be executed, sv2 stays in the top of Service_Start (last line below).

The project is attached. Thanks

 

Attachments

  • example.zip
    9 KB · Views: 214

Erel

B4X founder
Staff member
Licensed User
Longtime User
These are the complete logs I see when I run your app:
B4X:
*** Service (starter) Create ***
** Service (starter) Start **
File exists
Read: 2 entries
N is now created
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
*** Service (sv1) Create ***
** Service (sv1) Start **
*** Service (sv2) Create ***
** Service (sv2) Start **
sv2 entered Service_Start
sv2 StartedForeground
Timer1 initialized: true
Timer1 enabled: true
** Service (sv1) Destroy **
** Activity (main) Pause, UserClosed = false **
sending message to waiting queue (sleep)
App is killed
*** Service (sv1) Create ***
** Service (sv1) Start **
sv2 is still running...
** Service (sv1) Destroy **

I've changed Service_Start of sv1 to:
B4X:
Sub Service_Start (StartingIntent As Intent)
   DateTime.TimeFormat="HH:mm:ss"
   DateTime.DateFormat="dd/MM/yy"
   CallSubDelayed2(Starter,"SaveL0",$"sv1 - $date{(DateTime.now)} - $Time{(DateTime.Now)}"$)
   If IsPaused(sv2) Then
       StartService(sv2)
   Else
       Log("sv2 is still running...")
   End If
   StopService(Me)
End Sub
As you can see sv2 is never killed. The process itself is not killed when you swipe the app. This is the expected behavior: https://www.b4x.com/android/forum/t...-app-from-the-recent-apps-list.27605/#content
 
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
Thanks for your reply and analysis. So, in such case, the Timer which is inside sv2 should continue ticking ; or am I wrong ? Because, as far I saw, (with a short delay of 10 seconds), it was no more.

In the post you mentioned, why is the notification killed if the foreground service (sv2) is not killed ?
Erel said:
Foreground services (Service.StartForegroud) are not affected. This is also the only case where the process is not killed.

Thanks
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I've changed your code in sv2 to:
B4X:
Sub Service_Create
   PWS.PartialLock
   Timer1.Initialize("Timer1",(DateTime.TicksPerSecond*10))
   Timer1.Enabled = True
   Service.StartForeground(1,Starter.N)
   Log("sv2 StartedForeground")
End Sub

Sub Service_Start (StartingIntent As Intent)
   
End Sub

It is better to use Service_Create over Service_Start as Service_Create only runs once.

When I kill the app with a swipe (not a task manager) the notification icon is kept and the timer continues to run.
 
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
Hello,
I am sorry, I still get the same behavior. I have made a short video as proof and asked someone to host it.
The only things I changed from the improvements you advised, is to add ToastMessageShow as I made the recording using B4A 7.80 b2 directly so the logs won't be shown. I have shortened the Timer delay to 10s to be able to check quickly. My code is attached. The apk is attached too.


What I saw is :
- the notification is killed and recreated (as seen on the video)
- sv2 was not working and was restarted by sv1
- the timer was not ticking anymore (in fact, as I told previously, even if I put a Log or something inside the Service_Start of sv2, as the first line, that line is never executed when the service is killed by swiping)

Question : could it be possible that my B4A's setup is the reason why I (not so often but often) get such differences ? I use Android-27 and JDK 1.8.0_144 (64 bits). I compile in Release (obfuscated).

Many thanks
 

Attachments

  • CodeUsedForVideo.zip
    9.1 KB · Views: 164
  • apk.zip
    145.6 KB · Views: 188
Last edited:
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
Are you using a custom launcher?
The launcher installed on the client's phone is Google Now Launcher and on mine (the one used for the video) is Lenovo Launcher. But, in my opinion, it is not the launcher because, on your suggestion I tried two others (Microsoft and MiUI) with the same behavior. Something more with the system, maybe ?

Here are the logs :

Unfiltered logs attached too



EDIT : I have just tried with my own phone (Launcher3 installed) and I get the same​
 

Attachments

  • unfilteredLogs.zip
    45.9 KB · Views: 162
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
That's not that. What wonders me in this case is the last line of the log (tested on the same phone as the video). Could sv1 being destroyed before its resumable sub is ended ?
Perhaps something with multicore processors ?

 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
It seems like something with the combination of the foreground service and the sticky service doesn't work properly on your device. The behavior might depend on the OS version.

Change sv2 code to:
B4X:
Sub Service_Create
   Init
End Sub

Sub Service_Start (StartingIntent As Intent)
   Init
   WriteNow
End Sub

Sub Init
   Log("Init: " & Timer1.IsInitialized)
   If Timer1.IsInitialized = False Then
       PWS.PartialLock
       Timer1.Initialize("Timer1",(DateTime.TicksPerSecond*10))
       Timer1.Enabled = True
       PrepareNotification
       Service.StartForeground(1,N)
       Log("sv2 StartedForeground")
   End If
End Sub

'other code here

Does the timer start?
 
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
The timer does start when the app is started. But does not tick anymore when the app was killed.

I am not smart enough to understand the java code B4A produced but don't you think the problem could be inside the sub which prints "** Service (sv2) Start **"
I ask because it is the first and only thing that is done when the service should be restarted.
B4X:
private void handleStart(android.content.Intent intent) {
     BA.LogInfo("** Service (sv2) Start **");
     java.lang.reflect.Method startEvent = processBA.htSubs.get("service_start");
     if (startEvent != null) {
      if (startEvent.getParameterTypes().length > 0) {
       anywheresoftware.b4a.objects.IntentWrapper iw = new anywheresoftware.b4a.objects.IntentWrapper();
       if (intent != null) {
        if (intent.hasExtra("b4a_internal_intent"))
         iw.setObject((android.content.Intent) intent.getParcelableExtra("b4a_internal_intent"));
        else
         iw.setObject(intent);
       }
       processBA.raiseEvent(null, "service_start", iw);
      }
      else {
       processBA.raiseEvent(null, "service_start");
      }
     }
    }

This evening I will try with using a static broadcast receiver (I have no idea if it will work or not).
EDIT: the intent idea did not work, same result
 
Last edited:
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
If I do add another service (here s_v3) with the same code as sv2, it seems that sv2 is working as expected alternatively with s_v3 (without being able to know which will continue running ; same code) :



 

Attachments

  • 2.zip
    10.1 KB · Views: 194
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
It seems like you are hitting this Android bug: https://issuetracker.google.com/issues/36967794
It causes the foreground service to misbehave.

A possible workaround is to stop the foreground service in TaskRemoved:
B4X:
Sub Service_TaskRemoved
   SetExactAndAllowWhileIdle(DateTime.Now+DateTime.TicksPerSecond * 10,"sv1")
   StopService(sv2)
   Log("App is killed")
End Sub

Sub SetExactAndAllowWhileIdle (Time As Long, ServiceName As String)
   Dim p As Phone
   If p.SdkVersion < 23 Then
       StartServiceAtExact(ServiceName, Time, True)
   Else
       Dim in As Intent
       in.Initialize("", "")
       in.SetComponent(Application.PackageName & "/." &  ServiceName.ToLowerCase)
       Dim jin As JavaObject = in
       jin.RunMethod("setAction", Array(Null))
       Dim ctxt As JavaObject
       ctxt.InitializeContext
       Dim am As JavaObject = ctxt.RunMethod("getSystemService", Array("alarm"))
       Dim pi As JavaObject
       pi = pi.InitializeStatic("android.app.PendingIntent").RunMethod("getService", _
         Array(ctxt, 1, in, 134217728))
       am.RunMethod("setExactAndAllowWhileIdle", Array(0, Time, pi))
   End If
End Sub

This works properly here, though I tested it with a device that doesn't encounter this bug.
 
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
I do confirm that the workaround seems to work and do thank you for having provided so much support.
It is an example of what I told previously where I can not determine myself if it is Java or B4A. I have to apologize too.
 
Upvote 0

lemonisdead

Well-Known Member
Licensed User
Longtime User
FYI : if the workaround worked by me, it didn't for the client's phone. I guess we can't do better and will search Google groups as you did found the previous solution there.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…