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:

PSEAD

Member
Licensed User
Longtime User
I meant to ask if it would be good practice to kill it when exiting an app completely to stop the service using resources unnecessarily?
i.e. to free up memory without having to rely on android to do so.
You don't recommend killing the starter service -- would this apply even when it is no longer needed?
 

lemonisdead

Well-Known Member
Licensed User
Longtime User
You don't recommend killing the starter service -- would this apply even when it is no longer needed?
Hello,
I guess Erel was thinking about stopping the Starter service when the activity was put on pause. But, as told you previously it is a service only and you have to decide if you want to stop it when you don't need it anymore.
The decision is yours :
  • if you don't stop it, when you restart the app the service restarts. This means that if it was not killed previously you can retrieve previously stored values in Process_Globals variables
  • if you stop it, you restart with brand new Process_Globals
 

PSEAD

Member
Licensed User
Longtime User
That is a good point. An end user's first reaction when encountering a problem could be to close and restart the app, assuming that this would reset all variables. Without specifically terminating the starter service, closing and opening an application would not reset anything, possibly causing some confusion.
I guess it would depend on the application, but certainly something to be aware off. I have tested this effect using the "programflow" example and it does exactly as expected.
 

ivan.tellez

Active Member
Licensed User
Longtime User
It's somenting weird with android.

I have an App with 5 activities, If the app is not on the main activity and the user presses the home button, the app will send to background, after some time is killed (partial)

As Erel said;
the OS can start the process from a different activity

So the process was killed, but when the app is launched, android insist on launch another Activity (instead of Main)

Starter service resolves this partially, now, starter is allways the entry point and can initialize and launch Main Activity. BUT when the activity that was originaly intended to launch by android, has some objects initialized o_O

So, Is there a proper way to know in the starter service if an activity is initialized and kill it?

Thanks
 

ilan

Expert
Licensed User
Longtime User
The starter service should be excluded from compiled libraries. Its #ExcludeFromLibrary attribute is set to True by default

i have not understood this sentence, can someone explain to me what it says? (in simple english please :D)
 

klaus

Expert
Licensed User
Longtime User
You can compile modules to a library.
By default all modules are included exept the Main module which is automatically excluded from the library the Starter service is also excluded by default, because on top you have #ExcludeFromLibrary: True.
#Region Service Attributes
#StartAtBoot: False
#ExcludeFromLibrary: True

#End Region


Lets' take an example:
You have the Main module, two Class modules and one Code module.
The Code module is only for testing.
Now you want to compile both Classes into a library but without the Code module.
For that you must add #ExcludeFromLibrary: True on top of the Code module.
#Region Activity Attributes
#FullScreen: False
#IncludeTitle: True

#End Region
#ExcludeFromLibrary : True
 

ilan

Expert
Licensed User
Longtime User
Thanx klaus. I didnot knew that i can compile a module to a library.

So that means i can create a code module and then create from it a lib to use it in all my apps instead of copying that module?

So it is possible to create libs without knowing java??
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
So it is possible to create libs without knowing java?
As they are based on B4A Source, yes.

You can have a look at my Dropbox Class.
DropboxV2_libraryfiles_v093.zip is the Class compiled to a Library
The Class is inside DropboxHTTPv2librarysource_V0.93.zip

Try to open the project inside.
You see a blank main module but note the additional commands in Region Project attributes
B4X:
    #LibraryVersion: 0.93
    #LibraryAuthor: DonManfred <[email protected]>
    #LibraryName: DropboxHttpAPI

a blank starter and the dropboxclass itself...

Use Compile to Library on this project
It will - based on #LibraryName: DropboxHttpAPI - create a DropboxHttpAPI.jar and a DropboxHttpAPI.xml inside your additional libraries folder.

The result is that from now you can use the library DropboxHttpAPI to use the Dropboxclass. No need to add the Class-module to your project.
 
Last edited:

ValDog

Active Member
Licensed User
Longtime User
Based on what I've read in this thread am I correct in assuming that "Starter:Service_Create" is only called one time - upon application startup. So instead of using "If FirstTime" calls in my "Main:Activity_Create" I could instead place those items in "Starter:Service_Create?"
 

luke2012

Well-Known Member
Licensed User
Longtime User
If I execute an Activity.Finish statment within the Main module the Stater still running?
 

luke2012

Well-Known Member
Licensed User
Longtime User
Yes. It will be running until Android kills the process.

You can call StopService (Starter) if you like to manually stop it.

Thanks for the reply @Erel. In my case this is perfect because I need that the starter still running :)
 

bgsoft

Well-Known Member
Licensed User
Longtime User
Hi

This code does not work when the device is restarted (main does not run):
B4X:
'  Starter Service
#Region  Service Attributes
   #StartAtBoot: true
   #ExcludeFromLibrary: True
#End Region


Sub Service_Create
   StartActivity(Main) 
End Sub

This is the Log:
** Service (starter) Create **
** Service (starter) Start **
** Service (starter) Start **

This same code in a "normal" service module, if running Main

Why? :D the starter Service behaves different service modules ?. I have looked at the forum and I have not seen any explanation

Note: If I run the application from the desktop runs well.

This is the Log:
** Service (starter) Create **
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **


regards
 
Status
Not open for further replies.
Top