Android Tutorial Starter Service - Consistent & Single Entry Point

Status
Not open for further replies.
One of the challenges that developers of any non-small Android app need to deal with, is the multiple possible entry points.

During development in almost all cases the application will start from the Main activity.
Many programs start with code similar to:
B4X:
Sub Activity_Create (FirstTime As Boolean)
If FirstTime Then
  SQL.Initialize(...)
  SomeBitmap = LoadBitmap(...)
  'additional code that loads application-wide resources
End If
End Sub

Everything seems to work fine during development. However the app "strangely" crashes from time to time on the end user device.
The reason for those crashes is that the OS can start the process from a different activity or service. For example if you use StartServiceAt and the OS kills the process while it is in the background.
Now the SQL object and the other resources will not be initialized.

Starting from B4A v5.20 there is a new feature named Starter service that provides a single and consistent entry point. If the Starter service exists then the process will always start from this service.

The Starter service will be created and started and only then the activity or service that were supposed to be started will start.
This means that the Starter service is the best place to initialize all the application-wide resources.
Other modules can safely access these resources.
The Starter service should be the default location for all the public process global variables. SQL objects, data read from files and bitmaps used by multiple activities should all be initialized in the Service_Create sub of the Starter service.

Notes

  • The Starter service is identified by its name. You can add a new service named Starter to an existing project and it will be the program entry point.
  • This is an optional feature. You can remove the Starter service.
  • You can call StopService(Me) in Service_Start if you don't want the service to keep on running. However this means that the service will not be able to handle events (for example you will not be able to use the asynchronous SQL methods).
  • The starter service should be excluded from compiled libraries. Its #ExcludeFromLibrary attribute is set to True by default.
  • The starter service should never be explicitly started. This means that if you want to start a service at boot then add a different service.
Android 8+ considerations
  • Starting from Android 8, the OS kills services while the app is in the foreground.
  • If you are using B4A v8.30+ then the starter service will not be killed until the whole process is killed.
  • You will see a message such as this one, 60 seconds after the app has moved to the background:
    ** Service (starter) Destroy (ignored)**
  • The above message means that the actual service is destroyed but the starter service is still available.
  • Don't make the starter service a foreground service. It will not work once the backed service is destroyed.
  • If you want to do a background task then you should add another service.
  • Related tutorial: Automatic Foreground Mode
 
Last edited:

Roycefer

Well-Known Member
Licensed User
Longtime User
I thought you said the List access occurs in the Starter service. Why is the error occurring in Activity_Create?
 

JNG

Member
Licensed User
Hi Erel,

I am accessing data from remote server. Some of the part of the data I don't need upfront it is required on demand basis. To avoid memory leakage I want to access the same as an when require. Can I call starter service again in this case to do the job.

thanks
 

Dave O

Well-Known Member
Licensed User
Longtime User
In Erel's recent "tips for B4X developers" post (which motivated me to clean up my code), he states that "Public (process_global) variables should be declared and set / initialized in Service_Create of the Starter service".

I understand that it's best to initialize/assign values to those public variables in Starter > Service_Create, because it's the only guaranteed entry point.

However, does it really matter where we declare our Process_Global variables - in Starter, or a common code module, or an activity?

There are a few reasons I ask this:
- I typically put PG variables in a common code module called "c", so the prefix is kept short when referenced from other modules (e.g. c.someVariable instead of Starter.someVariable). It reduces clutter a bit.
- If a PG variable is mostly used in a single module (and rarely referenced outside it), I usually put the variable in that module to keep it "close to home" (and to avoid prefixing in most cases).
- I'm hoping to minimize the amount of code I need to move around, probably because I'm lazy. :)

Thanks!
 

ArminKH

Well-Known Member
In Erel's recent "tips for B4X developers" post (which motivated me to clean up my code), he states that "Public (process_global) variables should be declared and set / initialized in Service_Create of the Starter service".

I understand that it's best to initialize/assign values to those public variables in Starter > Service_Create, because it's the only guaranteed entry point.

However, does it really matter where we declare our Process_Global variables - in Starter, or a common code module, or an activity?

There are a few reasons I ask this:
- I typically put PG variables in a common code module called "c", so the prefix is kept short when referenced from other modules (e.g. c.someVariable instead of Starter.someVariable). It reduces clutter a bit.
- If a PG variable is mostly used in a single module (and rarely referenced outside it), I usually put the variable in that module to keep it "close to home" (and to avoid prefixing in most cases).
- I'm hoping to minimize the amount of code I need to move around, probably because I'm lazy. :)

Thanks!
as the starter service will never killed as long as your app is running so is the best point for initializes or hold resources(Global resources)
otherwise some time activity or code module will be closed by OS or mistakenly by yourself so your app will be crashed
imagine you have a service which started by ServiceStartAt at background and uses an sql object or an image which is declared and initialized in Code Module
now can your service get access to that sql object or image if your app is closed!!!?
as @Erel said
"The Starter service will be created and started and only then the activity or service that were supposed to be started will start."
so any time your activity or service or code/class modules need to any resources then all of them has a trusted point to access wide resources
Concise writing is not always good
 
Last edited:

Dave O

Well-Known Member
Licensed User
Longtime User
imagine you have a service which started by ServiceStartAt at background and uses an sql object or an image which is declared and initialized in Code Module. now can your service get access to that sql object or image if your app is closed!!!?
That's basically my question right there - if I declare my image in a code module, and initialize it in the Starter>Service_Create, is that OK?
I'm assuming that when the Starter service is called, all the Process_Globals variables are declared first (regardless of module), in which case it shouldn't matter where each variable is declared (as long as it's PG). Is that correct?
 

klaus

Expert
Licensed User
Longtime User
The Program flow at start is:

Main.Process_Globals
Starter.Process_Globals
Other Activity.Process_Globals
Other CodeModule.Process_Globals
Starter.Service_Create
Starter.Service:Start
Main.Globals
Main.Activity_Create
Main.Activity_Resume
 

Dave O

Well-Known Member
Licensed User
Longtime User
@klaus , thanks for that.

And I assume that the last 3 items (Main module) might be replaced by another activity in those edge cases that Erel mentioned?
 

Mahares

Expert
Licensed User
Longtime User
Main.Process_Globals
Starter.Process_Globals
@klaus: i always thought the order should be the below, since the starter service is the initial entry point of any application that has it:
Starter.Process_Globals
Starter.Service_Create
Starter.Service:Start
Main.Process_Globals
I was basing my assumption based on this Erel's statement in his Starter tutorial:
The Starter service will be created and started and only then the activity or service that were supposed to be started will start.
Could you please enlighten us.
 

PSEAD

Member
Licensed User
Longtime User
I am busy rewriting some old code to clean it up, and I just want to confirm, given the results of "programflow": Am I correct in assuming that Process_Globals declared in code modules would therefore be treated the same as if they were declared in the starter process, and would be fine as long as the service is active?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Am I correct in assuming that Process_Globals declared in code modules would therefore be treated the same as if they were declared in the starter process, and would be fine as long as the service is active?
That's correct (they will also be "fine" even if the service is no longer active).

As a general recommendation all public process globals should be declared in Starter service and initialized in Service_Create.
 

PSEAD

Member
Licensed User
Longtime User
Thanks. Good news. It just becomes a problem declaring them in the starter service when using common code modules used by a few different apps.
 

PSEAD

Member
Licensed User
Longtime User
It looks like the stater service continues to run after the main activity is closed. (In my case this is good because I am using a kiosk service).
Under what conditions, besides stopping the service in code, would the service stop running?
Should we kill the starter service in the activity_pause event?
 

lemonisdead

Well-Known Member
Licensed User
Longtime User
Under what conditions, besides stopping the service in code, would the service stop running?
Hello,
The system will kill the service when it needs more resources. But I guess it could be put as Sticky like any other services (https://www.b4x.com/android/forum/t...-long-running-background-tasks.27065/#content) ~to be confirmed ~
Should we kill the starter service in the activity_pause event?
In fact it is a "service" so you should or shouldn't stop it depending on what you need to be done. It's your choice.
 
Status
Not open for further replies.
Top