Android Tutorial Automatic Foreground Mode

Discussion in 'Tutorials & Examples' started by Erel, Mar 12, 2018.

Thread Status:
Not open for further replies.
  1. Erel

    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:
    Code:
    Sub Service_Start (StartingIntent As Intent)
       fm.HandleIntent(StartingIntent)
       Sleep(
    0'allow the MessageReceived event to be raised.
       Service.StopAutomaticForeground
    End Sub
    Widgets:
    Code:
    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: Jun 12, 2018
  2. kisoft

    kisoft Active Member Licensed User

  3. Erel

    Erel Administrator Staff Member Licensed User

    This is indeed a case where the service will start from the background.
    Add Service.StopAutomaticForeground before the end of Service_Start.
     
  4. kisoft

    kisoft Active Member Licensed User

    I will ask if it is good
    Code:
    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
     
    pesquera likes this.
  5. Erel

    Erel Administrator Staff Member Licensed User

    pesquera likes this.
  6. kisoft

    kisoft Active Member Licensed User

    Thank you.
     
  7. Alessandro71

    Alessandro71 Member Licensed User

    should we add
    Service.StopAutomaticForeground
    to our Starter service in existing project?
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    It will not do any harm though it is not needed. The starter service is never started from a receiver.
     
    pesquera likes this.
  9. johndb

    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: Mar 13, 2018
    pesquera, Multiverse app and Erel like this.
  10. Erel

    Erel Administrator Staff Member Licensed User

    Good. For now I recommend you to set the targetSdkVersion to 26.
     
    pesquera and johndb like this.
  11. rscheel

    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?
     
  12. johndb

    johndb Active Member Licensed User

    Yes, they will.
     
    pesquera and rscheel like this.
  13. asales

    asales Well-Known Member Licensed User

    I has this code to the notification:
    Code:
    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/6015+30/6020+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)?
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    Yes. It will work properly with the default automatic mode. The automatic notification will not be visible at all as you are immediately stopping the service (which is fine).

    It is better to call StopService(Me) though both options will work.
     
    asales likes this.
  15. pesquera

    pesquera Active Member Licensed User

    Is
    unsafe to use with Android 8+?

    On Service_Create I have this code:
    Code:
    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:
    Code:
    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)?
     
  16. Erel

    Erel Administrator Staff Member Licensed User

    No.

    Are you setting it in Service_Create?

    Both options are good and should show the notification icon.
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    Tutorial was updated with Services life cycle in Android 8+ section.
     
    pesquera and lemonisdead like this.
  18. pesquera

    pesquera Active Member Licensed User

    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
     
  19. Erel

    Erel Administrator Staff Member Licensed User

    You should set Service.AutomaticForegroundMode in Service_Create. Otherwise it will be ignored.

    If you have any other question then please start a new thread.
     
    pesquera likes this.
  20. Computersmith64

    Computersmith64 Well-Known Member Licensed User

    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: Mar 25, 2018
Thread Status:
Not open for further replies.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice