Android Tutorial Automatic Foreground Mode

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User
This is a new feature added in B4A v8.0.

Starting from Android 8.0, services cannot be simply started while the app is in the background or not running at all. Background means that there isn't any visible activity or any service in foreground state (Service.StartForeground).

Common cases where we expect services to start even if the app is not in the foreground:

- Push notifications
- Services scheduled with StartServiceAt or StartServiceAtExact
- Services set to start after boot with #StartAtBoot attribute
- Home screen widgets

The only way for services to start when the app is not in the foreground is with a new API that ensures that the service will start and immediately switch to foreground mode.
This is now handled automatically in the B4A framework. When needed services automatically start in foreground mode.
Needed = Running on Android 8+ and the app is considered in the background when the service is started.

You need to do one thing which is to stop the automatic foreground mode when the service completed its task.
This can be done in two ways:

1. Call Service.StopAutomaticForeground. This will stop the automatic foreground mode if the service was in that mode. Otherwise it will not do anything.
It is safe to call it multiple times. The service will not be immediately destroyed.

2. Call StopService(Me).

If you don't stop the automatic foreground mode then a notification icon will be left after the task completed.

For example if you are receiving push notifications:
B4X:
Sub Service_Start (StartingIntent As Intent)
   fm.HandleIntent(StartingIntent)
   Sleep(0) 'allow the MessageReceived event to be raised.
   Service.StopAutomaticForeground
End Sub
Widgets:
B4X:
Sub Service_Start (StartingIntent As Intent)
   rv.HandleWidgetEvents(StartingIntent)
   Sleep(0)
   Service.StopAutomaticForeground
End Sub
Note that the foreground icon will not be visible at all when the task completes almost immediately.

Service.AutomaticForegroundMode - This is a new property that you can set in Service_Create to override the default behavior.
The possible values are:

Service.AUTOMATIC_FOREGROUND_WHEN_NEEDED - This is the default value. The service will enter foreground mode when needed as described above.

Service.AUTOMATIC_FOREGROUND_NEVER - It will never enter foreground mode. This means that you must call Service.StartForeground when needed or your app will crash.

Service.AUTOMATIC_FOREGROUND_ALWAYS - Service will always start in foreground mode, on all versions of Android. This can be useful if you want to make sure that the app is not killed until the task completes. Note that you should also acquire a partial wake lock.

Another new property is Service.AutomaticForegroundNotification. This allows you to change the notification that appears in automatic foreground mode.

Services life cycle in Android 8+

This is not related to automatic foreground mode however it is another thing that you should be aware of when working with services in Android 8+.
Up until Android 7, the OS never killed the app services. Instead when the app was in the background it killed the complete process. Service_Destroy was never called in those cases.

Starting from Android 8, when the app is in the background (no activities and no foreground services), the OS can kill services without killing the process. In those cases the Service_Destroy sub will be called.
This means for example that we can no longer assume that the starter service is always running. It will be started when the process starts however later it can be destroyed.
You can call StartService or CallSubDelayed whenever an activity is resumed to make sure that the relevant service is started.
Note that process global variables are tied to the process and will not be destroyed when the service is stopped.

Update: Starting from B4A v8.3 the starter service will never be killed unless the whole process is killed. This means that you can always assume in your code that the starter service is running.
It is done internally by changing the starter service context to the application context.
 
Last edited:

kisoft

Well-Known Member
Licensed User
I will ask if it is good
B4X:
Sub Service_Start(startingIntent As Intent)
    
    If startingIntent.Action = "android.provider.Telephony.SMS_RECEIVED" Then
        Dim messages() As Message
        messages = ParseSmsIntent(startingIntent)
        For i = 0 To messages.Length - 1
            Log(messages(i))
        Next
        Service.StopAutomaticForeground
    End If
End Sub
 

johndb

Active Member
Licensed User
I ran some tests with B4A 8.0 Beta and can confirm that FCM works well in background using a target SDK 27 where it had failed (crashed) using 7.8 in the past (Android 8.1.0). Thank you!
 
Last edited:

rscheel

Well-Known Member
Licensed User
If the applications are updated with this, will they continue to work with an Android version lower than 8.0?
 

asales

Well-Known Member
Licensed User
I has this code to the notification:
B4X:
Sub Service_Start (StartingIntent As Intent)
   (...)

   n.SetInfo2(MyText1, MyText2, "MyNotify", Main)
   n.Notify(1)   

   Dim t As Long
   t = FindNextTime(Array As Double(8+30/60, 15+30/60, 20+30/60))

   StartServiceAt(Me,t,True)
   StopService("")
End Sub
This code is correct to migrate to B4A v.8?
I can use StopService("") instead StopService(Me)?
 

pesquera

Active Member
Licensed User
Is
Service.StartForeground
unsafe to use with Android 8+?

On Service_Create I have this code:
B4X:
GLO_NotificationSvc.Initialize
GLO_NotificationSvc.Icon = "icon"
GLO_NotificationSvc.Sound = False
GLO_NotificationSvc.SetInfo("Title","Body",Main)
Service.StartForeground(123456789,GLO_NotificationSvc)
If I replace that code with this one:
B4X:
Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_ALWAYS
Everything runs Ok
But, the app Icon on the Notifications area does not appear

1) What code is safer?
2) How can I do if want to show the app Icon on the Notifications area (upper)?
 

pesquera

Active Member
Licensed User
Are you setting it in Service_Create?
Both options are good and should show the notification icon.
Yes

Sorry, I don't understand the differences between both methods yet
Could you explain please about the differences?

One method is the replacement of the another one?
What happen if I use both together?

The behavior on my app is this:
Service.StartForeground(123456789,GLO_NotificationSvc) -> Shows the app notification icon (upper on the device)
Service.AutomaticForegroundMode = Service.AUTOMATIC_FOREGROUND_ALWAYS -> Does not show the app notification icon (upper on the device)

If this is not the normal behavior, what can I see to fix it?

Thanks very much
 

Computersmith64

Well-Known Member
Licensed User
Starting from Android 8, when the app is in the background (no activities and no foreground services), the OS can kill services without killing the process. In those cases the Service_Destroy sub will be called.
This means for example that we can no longer assume that the starter service is always running. It will be started when the process starts however later it can be destroyed.
You can call StartService or CallSubDelayed whenever an activity is resumed to make sure that the relevant service is started.
Note that process global variables are tied to the process and will not be destroyed when the service is stopped.
I'm starting to see crash reports from Android 8 devices where there is a null pointer exception when trying to access objects & variables declared in the Starter service. I assume it's because the app has been in the background & the Starter service has been killed by the OS.

In my case, I call some variables & subs that are in the Starter service from Activity_Create - so what's the best solution for making sure that the Starter service is running? Starting it from Activity_Resume is going to be too late, so is it safe to put a StartService(Starter) call right at the start of Activity_Create - or is there a better solution?

- Colin.
 
Last edited:
Status
Not open for further replies.
Top