Kill Service

etLux

Member
Licensed User
Longtime User
Let's say I have an app running (Main module).

And I have a notification running from a service (Notifier module).

If the app (Main) is killed, either by Android OS or, say, a utility like Advanced Task Killer -- the service (in this case, Notifier) appears to remain running.

How do I get the Notifier service to die if the Main module is killed?

Edit:

Come to think of it, I guess what I'm asking here is how to have the Notifier service check to see if its related Main is still running...?

Thanks!

Best,



David
------
David Sosnowski
The Music of David Sosnowski
 
Last edited:

etLux

Member
Licensed User
Longtime User
You can use IsPaused(Main) to check whether the activity is running or paused.

Thanks, Erel, but that's not quite the difficulty I'm having.

In this case, Main no longer exists. If I use IsPaused(Main),
say, in a timer loop in the Notifier service -- it cannot find Main
to test; and therefore throws a "closed unexpectedly" error
and forces a close...

How might I test from the my Notifier service to see if Main
still exists?

Thank you, Erel!

All the best,



David
-----
David Sosnowski
The Music of David Sosnowski
 
Upvote 0

etLux

Member
Licensed User
Longtime User
B4X:
Sub timerN_Tick

   Try
   If Main.MP.IsPlaying Then MainThere = True
   'We really don't care of MP is playing or not...
   'This is a dummy test to see if Main is still there [this could be a test on any global in Main]
   Catch
   n.Cancel(1)   
   'If Main is gone it'll catch the error (no MP found) and close the notification
   End Try

End Sub

Using a timer sub in the Notifier module with a try-catch seems to work.

I'm a little shaky on this, though -- is this an acceptable way to go about it?

Best,



David
-----
David Sosnowski
The Music of David Sosnowski
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
In this case, Main no longer exists. If I use IsPaused(Main),
say, in a timer loop in the Notifier service -- it cannot find Main
to test; and therefore throws a "closed unexpectedly" error
and forces a close...
Main module should always exist. Can you post the exact error that you encounter when calling IsPaused.
 
Upvote 0

etLux

Member
Licensed User
Longtime User
Main module should always exist. Can you post the exact error that you encounter when calling IsPaused.

Hello Erel,

I should emphasize that this is a specialized case that
occurs only when I kill the app with Advanced Task Killer --
but in that task killers of one kind or another are widely
used, I felt I should handle it, regardless.

The general scenario lays out like this...

1.)

The app is running, and I kill it with Advanced Task Killer.
But the notification service remains running and displayed
in the notification area indefinitely, as though the app were
still running.

2.)

Initially, to combat that, I tested on IsPaused(Main) from
a timer sub. But when the test checked IsPaused(Main),
the OS would throw a non-specific error that basically
says nothing more than that the app closed unexpectedly.
I therefore (perhaps incorrectly?) assumed that Main was
no longer running -- but the service was.

3.)

That led me to the try-catch in a timer sub as shown above,
which successfully closes the notification without error.

Erel, I'm not sufficiently knowledgeable to say why
a service might remain when the app is killed by a task
killer; nor even if I am correctly interpreting what I am seeing.

The only other approach [which I would normally use in other
operating systems] might be to kill the service via an
On_Before_Close event -- but I'm unaware of a way to do
that in Android. Is there one...?

Always best,


David
-----
David Sosnowski
The Music of David Sosnowski
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
There isn't enough detail as to what you are actually doing in this scenario to invoke the service but I guess what is happening is that your process is being restarted because the service is being restarted but as your main activity is not started so you get the error.

Do you you have a service start scheduled when you kill the process and is that bringing it back to life?
 
Upvote 0

etLux

Member
Licensed User
Longtime User
There isn't enough detail as to what you are actually doing in this scenario to invoke the service but I guess what is happening is that your process is being restarted because the service is being restarted but as your main activity is not started so you get the error.

Do you you have a service start scheduled when you kill the process and is that bringing it back to life?

Thank you for your comments, agraham, I appreciate your interest.

Here is the Main:

B4X:
Sub Process_Globals
    Dim theVersion As String
   theVersion = "1.00"
   Dim MP As MediaPlayer
   Dim timer1 As Timer   
   Dim nowVolume As Int
   Dim nowPosition As Int
   Dim positionBarText As String   
End Sub

Sub Globals
   Dim cd_blue As ColorDrawable
   Dim barPosition As SeekBar
   Dim barVolume As SeekBar
   Dim Stop As Button
   Dim LinkTo As Button
   Dim volumeLabel As Label
   Dim positionLabel As Label
   Dim Quit As Button
   Dim Title As Label
   Dim Composer As Label
   Dim Info As Button
   Dim Rewind As Button
   Dim M As String
   Dim debugText As Label
End Sub

'    CREATE

Sub Activity_Create(FirstTime As Boolean) 

   If FirstTime Then
   
      MP.Initialize( )
      MP.Load(File.DirAssets, "lag100.mp3")   
      Timer1.Initialize("timer1", 100)
      nowVolume = 50
      nowPosition = 0
      positionBarText = "Position: 0:00 (8:18)"
      
      If File.Exists(File.DirInternal,"lagvol.txt") Then
         Dim vtext As String
          vtext = File.ReadString(File.DirInternal, "lagvol.txt") 
         nowVolume = vtext         
      End If
      
      StartService(Notifier)
            
   End If   ' end first time   
   
   Activity.LoadLayout("1")
   
   Activity.AddMenuItem2("Info","Info",LoadBitmap(File.DirAssets,"dialog-36.png"))
   Activity.AddMenuItem2("Link","LinkTo",LoadBitmap(File.DirAssets,"link-36.png"))   
   Activity.AddMenuItem2("Exit","Quit",LoadBitmap(File.DirAssets,"exit-36.png"))
   
   DoLayout
   
   barVolume.Value = nowVolume
   MP.SetVolume(barVolume.Value / 100, barVolume.Value / 100)   
         
   cd_blue.Initialize(Colors.Blue, 12dip)
    Stop.Background = cd_blue
      
End Sub

'   DO LAYOUT

Sub DoLayout
   
   Title.Top = 5%y
   Title.Width = 90%x
   Title.Left = 5%x
   
   Composer.Top = Title.Top + Title.Height
   Composer.Width = 90%x
   Composer.Left = Title.Left
   
   barPosition.Width = 42%x
   barVolume.Width = 42%x
   
   barVolume.Top = Composer.Top + Composer.Height + 2%y
   barPosition.Top = barVolume.Top
   
   barVolume.Left = 5%x
   barPosition.Left = 95%x - barPosition.Width
   
   volumeLabel.Top = barVolume.Top + barVolume.Height
   positionLabel.Top = volumeLabel.Top
   
   volumeLabel.Width = barVolume.Width
   positionLabel.Width = barPosition.Width
   
   volumeLabel.Left = barVolume.Left
   positionLabel.Left = barPosition.Left   
   
   Stop.Width = 18%x
   Rewind.Width = Stop.Width
   LinkTo.Width = Stop.Width
   Quit.Width = Stop.Width
   
   Stop.Top = positionLabel.Top + positionLabel.Height + 1.5%y
   Rewind.Top = Stop.Top
   LinkTo.Top = Stop.Top
   Quit.Top = Stop.Top
   
   Stop.Left = barVolume.Left
   Rewind.Left = (barVolume.Left + barVolume.Width) - Rewind.Width
   LinkTo.left = barPosition.Left
   Quit.Left = 95%x - Quit.Width   
   
   Info.Top = Title.Top
   Info.Left = 95%x - Info.Width   

End Sub

'   RESUME

Sub Activity_Resume   
   timer1.Enabled = True
   timer1_Tick 'update.
   barVolume.Value = nowVolume
   barPosition.Value = nowPosition   
   positionLabel.Text = positionBarText      
End Sub

'   PAUSE

Sub Activity_Pause (UserClosed As Boolean)
   nowVolume = barVolume.Value
   nowPosition = barPosition.Value
   positionBarText = positionLabel.Text
End Sub

'   TIMER

Sub timer1_Tick

   If MP.Position > (MP.Duration -2222) Then 
   Rewind_Click
   End If      
   
   'If MP.IsPlaying Then   
      barPosition.Value = MP.Position / MP.Duration * 100
      positionLabel.Text = "Position: " & ConvertToTimeFormat(MP.Position) & _
         " (" & ConvertToTimeFormat(MP.Duration-2000) & ")"   'fudge      
   'End If
   
   If MP.IsPlaying Then Stop.Text = "Stop" Else Stop.Text = "Play"   
   If MP.IsPlaying Then Stop.Color = Colors.Red Else Stop.Color = Colors.Blue   
   
   volumeLabel.Text = "Volume: " & barVolume.Value & "%"   
   MP.SetVolume(barVolume.Value / 100, barVolume.Value / 100)
   
End Sub

'   CONVERT milliseconds to m:ss format

Sub ConvertToTimeFormat(ms As Int) As String
   Dim seconds, minutes As Int
   seconds = Round(ms / 1000)
   minutes = Floor(seconds / 60)
   seconds = seconds Mod 60
   Return NumberFormat(minutes, 1, 0) & ":" & NumberFormat(seconds, 2, 0) 'ex: 3:05
End Sub

'   POSITION BAR CHANGE

Sub barPosition_ValueChanged (Value As Int, UserChanged As Boolean)
   If UserChanged = False Then Return 'value changed programmatically   
   MP.Position = Value / 100 * MP.Duration   
   If MP.IsPlaying = False Then 'happens when playback reached end and user changes position
      MP.Play
   End If   
   timer1_Tick 'immediately update   
End Sub

'   PLAY-STOP

Sub Stop_Click
   If MP.IsPlaying Then MP.Pause Else MP.Play
End Sub

'   REWIND

Sub Rewind_Click
   If MP.IsPlaying Then MP.Pause
   MP.Position = 0
   barPosition.Value = 0
   positionLabel.Text = "Position: 0:00 (8:18)"   
   Stop.Text = "Play"
   Stop.Color = Colors.Blue
   timer1_Tick
End Sub

'   LINK

Sub LinkTo_Click
   Dim p As PhoneIntents
    StartActivity(p.OpenBrowser("http://www.davidsosnowski.com/"))
End Sub


'   INFO

Sub Info_Click
   M = "Lucifer and Gandhi" & CRLF & "Piano & Symphony Orchestra" & CRLF & "David J. Sosnowski" & CRLF & CRLF & "Copyright 2006-2010 V" & theVersion
   'Msgbox(M,"Information")
   ToastMessageShow(M,True)
End Sub

'   QUIT

Sub Quit_Click

   Dim v As String
   v = barVolume.Value
   File.WriteString(File.DirInternal,"lagvol.txt",v)
   
   StopService(Notifier)
   Notifier.n.Cancel(1)   
   
   ExitApplication
   
End Sub

'   END OF PROGRAM

And here is the Notifier (service):

B4X:
'Service module
Sub Process_Globals
   Dim n As Notification
   Dim timerN As Timer
   Dim MainThere As Boolean
End Sub
Sub Service_Create
   n.Initialize
   n.OnGoingEvent = True
   n.Icon = "icon"
   n.SetInfo("Lucifer and Gandhi","Open the Lucifer and Gandhi app...",Main)
   n.Vibrate = False
   n.Sound = False   
   n.Light = False
   timerN.Initialize("timerN",1000)
   timerN.Enabled = True
End Sub

Sub Service_Start   
   n.Notify(1)
End Sub

Sub Service_Destroy

End Sub

Sub timerN_Tick
   Try
      If Main.MP.IsPlaying Then MainThere = True
      'We really don't care of MP is playing or not...
      'This is a dummy test to see if Main is still there [this could be a test on any global in Main]
   Catch
      n.Cancel(1)   
      StopService("")
      ExitApplication
      'If Main is gone it'll catch the error (no MP found) and close the notification
   End Try
End Sub

I may have some spaghetti in here -- but if I do, I'm not seeing it.

All the best,



David
-----
David Sosnowski
The Music of David Sosnowski
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
It would have been easier to post the project, File -> Export As Zip, then I could have tried it but I'm not spending time recreating what you already have done.

Is Service_Destroy being called? Try a Log statement in it.

Have you tried cancelling the notification in Service_Destroy?

Have you tried stopping the Timer in Service_Destroy?
 
Upvote 0

etLux

Member
Licensed User
Longtime User
Right hand pane. Logcat tab. Press Connect then run the program.

Awright. Now I'm really feeling dumber than dirt...
How do you copy the LogCat window? I right-click
over it, it says "Copy to clipboard". It copies the
single line I'm over -- but I cannot seem to find a
way to select the whole listing?

Best,



David
-----
David Sosnowski
The Music of David Sosnowski
 
Upvote 0

etLux

Member
Licensed User
Longtime User
Unfortunately you can't. I'm hoping Erel will change this in a future release but for now taking a screenshot is the easiest option.

I got a better idea... I've posted the 14M project zip file
here so it can be downloaded:

(Edit: link removed - DJS)

Let me know when you have that so I can remove it from
view.

Thanks!



David
-----
David Sosnowski
The Music of David Sosnowski
 
Last edited:
Upvote 0

agraham

Expert
Licensed User
Longtime User
That apk file is really a bit too large!

I've been puzzling over why I can't reproduce your problem and have realised that you have posted a version that doesn't actually exhibit the problem. :(

In Sub timerN_Tick the Try Catch is superfluous because MP is a Process_Global and will exist as long as the process, including the Service, exists so there is no possibility of an error.

I also get no error trying to use IsPaused(main) in the timer event.

With

Sub timerN_Tick
If Main.MP.IsPlaying Then MainThere = True
If IsPaused(Main) Then MainThere = True
End Sub

I start it playing.
I press back, Logcat says - ** Activity (main) Pause, UserClosed = true **
The Notification is there and music plays
Kill the process with Advance Task Killer
Music stops and Notification disappears.

I can't see any problem :confused:
 
Upvote 0

etLux

Member
Licensed User
Longtime User
That apk file is really a bit too large!

I've been puzzling over why I can't reproduce your problem and have realised that you have posted a version that doesn't actually exhibit the problem. :(

In Sub timerN_Tick the Try Catch is superfluous because MP is a Process_Global and will exist as long as the process, including the Service, exists so there is no possibility of an error.

I also get no error trying to use IsPaused(main) in the timer event.

With

Sub timerN_Tick
If Main.MP.IsPlaying Then MainThere = True
If IsPaused(Main) Then MainThere = True
End Sub

I start it playing.
I press back, Logcat says - ** Activity (main) Pause, UserClosed = true **
The Notification is there and music plays
Kill the process with Advance Task Killer
Music stops and Notification disappears.

I can't see any problem :confused:

Thank you for looking at it, Andew, I appreciate it! And yes, the
zipped version did contain my "solution" to the problem I was seeing.

Did you note earlier that I mentioned this is a special case -- that the
problem only occurs when the app is killed with a utility such as
Advanced Task Killer (or other task killer)?

You are correct that the app behaves well when closed normally
(from it's own "Quit" button, for instance).

The problem occurs when closed with a task killer -- whereupon
the Niotifier service remains running after the Main process no longer is.

At least that's what I see on my Droid X... and in that task killers
of one kind or another are fairly widely used, I felt I should handle
that problem in some manner.

All the best,



David
-----
David Sosnowski
The Music of David Sosnowski
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Did you note earlier that I mentioned this is a special case ...
Of course I noticed and tried to replicate it. If you carefully read to the end of my post above you will see that I document the changes I made to the Timer code and the sequence I used to try to see problem. I even made sure that I used Advanced Task Killer and found no problem. If it requires a different sequence to recreate it then let me know.
 
Last edited:
Upvote 0
Top