Android Tutorial Android Process and activities life cycle

New video tutorial:



Lets start simple:
Each B4A program runs in its own process.
A process has one main thread which is also named the UI thread which lives as long as the process lives. A process can also have more threads which are useful for background tasks.

A process starts when the user launches your application, assuming that it is not running already in the background.

The process end is less determinant. It will happen sometime after the user or system has closed all the activities.
If for example you have one activity and the user pressed on the back key, the activity gets closed. Later when the phone gets low on memory (and eventually it will happen) the process will quit.
If the user launches your program again and the process was not killed yet the same process will be reused.

A Basic4android application is made of one or more activities. Android support several other "main" components. These will be added to Basic4android in the future.

Activities are somewhat similar to Windows Forms.
One major difference is that, while an activity is not in the foreground it can be killed in order to preserve memory. Usually you will want to save the state of the activity before it gets lost. Either in a persistent storage or in memory that is associated with the process.
Later this activity will be recreated when needed.

Another delicate point happens when there is a major configuration change in the device. The most common is an orientation change (user rotates the device). When such a change occurs the current activities are destroyed and then recreated. Now when we create the activity we can create it according to the new configuration (for example, we now know the new screen dimensions).
How do we handle it? :confused:
When you create a new activity you will start with the following code template:
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

End Sub

Sub Activity_Create(FirstTime As Boolean)
 
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Variables can be either global or local. Local variables are variables that are declared inside a sub other than Process_Globals or Globals.
Local variables are local to the containing sub. Once the sub ends these variables no longer exist.
Global variables can be accessed from all subs.

There are two types of global variables.
Process variables and activity variables.

Process variables - These variables live as long as the process lives.
You should declare these variables inside sub Process_Globals.
This sub is called once when the process starts (this is true for all activities, not just the first activity).
These variables are the only "public" variables. Which means that they can be accessed from other modules as well.
However, not all types of objects can be declared as process variables.
All of the views for example cannot be declared as process variables.
The reason is that we do not want to hold a reference to objects that should be destroyed together with the activity.
In other words, once the activity is being destroyed, all of the views which are contained in the activity are being destroyed as well.
If we hold a reference to a view, the garbage collector would not be able to free the resource and we will have a memory leak.
The compiler enforces this requirement.

Activity variables - These variables are contained by the activity.
You should declare these variables inside Sub Globals.
These variables are "private" and can only be accessed from the current activity module.
All objects types can be declared as activity variables.
Every time the activity is created, Sub Globals is called (before Activity_Create).
These variables exist as long as the activity exists.

Sub Activity_Create (FirstTime As Boolean)
This sub is called when the activity is created.
The activity is created when the user first launches the application, the device configuration has changed (user rotated the device) and the activity was destroyed, or when the activity was in the background and the OS decided to destroy it in order to free memory.
This sub should be used to load or create the layout (among other uses).
The FirstTime parameter tells us if this is the first time that this activity is created. First time relates to the current process.
You can use FirstTime to run all kinds of initializations related to the process variables.
For example if you have a file with a list of values that you need to read, you can read it if FirstTime is True and store the list as a process variable.
Now we know that this list will be available as long as the process lives and there is no need to reload it even when the activity is recreated.

To summarize, you can test whether FirstTime is True and then initialize process variables.

Sub Activity_Resume and Sub Activity_Pause (UserClosed As Boolean)
Each time the activity moves from the foreground to the background Activity_Pause is called.
Activity_Pause is also called when the activity is in the foreground and a configuration change occurs (which leads to the activity getting paused and then destroyed).
Activity_Pause is the last place to save important information.
Generally there are two types of mechanisms that allow you to save the activity state.
Information that is only relevant to the current application instance can be stored in one or more process variables.
Other information should be stored in a persistent storage (file or database).
For example, if the user changed some settings you should save the changes to a persistent storage at this point. Otherwise the changes may be lost.

Activity_Resume is called right after Activity_Create finishes or after resuming a paused activity (activity moved to the background and now it returns to the foreground).
Note that when you open a different activity (by calling StartActivity), the current activity is first paused and then the other activity will be created if needed and (always) resumed.

As discussed above Activity_Pause is called every time that the activity moves from the foreground to the background. This can happen because:
1. A different activity was started.
2. The Home button was pressed
3. A configuration changed event was raised (orientation changed for example).
4. The Back button was pressed.

In scenarios 1 and 2, the activity will be paused and for now kept in memory as it is expected to be reused later.
In scenario 3 the activity will be paused, destroyed and then created (and resumed) again.
In scenario 4 the activity will be paused and destroyed. Pressing on the Back button is similar to closing the activity. In this case you do not need to save any instance specific information (the position of pacman in a PacMan game for example).
The UserClosed parameter will be true in this scenario and false in all other. Note that it will also be true when you call Activity.Finish. This method pauses and destroys the current activity, similar to the Back button.

You can use UserClosed parameter to decide which data to save and also whether to reset any related process variables to their initial state (move pacman position to the center if the position is a process variable).

A new module is available for handling the UI state: http://www.b4x.com/forum/basic4andr...ging-android-applications-settings-state.html

Now you should be ready for this short quiz:
http://www.b4x.com/android/forum/threads/quiz-12-find-the-bug-process-activities-life-cycle.37899/
Life cycle graphical diagram: http://www.b4x.com/android/forum/threads/graphical-life-cycle-of-a-b4a-activity.40515/

Starting from v5.20 there is a new feature named Starter Service that acts as a single program entry point: https://www.b4x.com/android/forum/threads/starter-service-consistent-single-entry-point.57599/
 
Last edited:

ilan

Expert
Licensed User
Longtime User
Yes. You are not loading any layout when FirstTime is False (which will happen after you press on the back key).

Note that it is a mistake to call Activity.Finish in Activity_Pause (not related to the missing layout).

hi erel, i am loading a layout on firsttime = false

the code i have posted is only from the main activity but this activity only show the logo then it starts the menu activity where you can see the code in the video and i am loading a layout also on firsttime = false

if i would not then also by clicking the home button it would not work, it is very strange the by clicking the home button it is ok but back button not
they do the same thing or am i wrong?

both will exit the activity and recreate it again by entering the activity again and there should be the same behaver for both process but it does not

***

i am finishing the activity on activity.pause because i dont want to enter it again it is only the logo activity and if i would not finish it i would get back to everytime i exit my app but i dont want to show again and again the logo activity, this is the reason i am finishing it
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Go over your code again. It's simply wrong. You are not starting the timer when FirstTime is False so the second activity never starts.

it is very strange the by clicking the home button it is ok but back button not
they do the same thing or am i wrong?
Sorry but I don't see anything strange here.
 

ilan

Expert
Licensed User
Longtime User
i will try to explain it again i hope you will understand me.. :confused:

i have 2 activities: Activity1 called "main", Activity2 called "menu"

main = only show the logo of my apps and should start activity "menu"
menu = is the menu of the game where you can choose Play, Exit, Settings,...


if i exit the game from the MENU activity to Andorid (by clicking the Home button) i want to return again to activity MENU and not to main (where only the logo is shown) thatswhy i call activity.finish in the main activity and thatswhy the timer starts only in firsttime = true because this activity should not be start again

if i would not finish activity "main" i will go to it if i press the back button in activity "menu" and i dont want it, why should someone see my logo by clicking the back button?!

so activity "main" is closed and wont load again so it does not matter if the timer is only in firsttime = true

everything is ok by clicking the Home button on activity "menu" and by returning to the app i get to activity menu (as it should be)
but if i press back button and the return to app it should return to activity menu like on the home button it does, or am i wrong?

could it be that it is returning to the main activity and because everything is called on firsttime = true i see a blank screen??? also after i called activity.finish ???
 

ilan

Expert
Licensed User
Longtime User
i think i understand now

back key = userclosed = true
home button = userclosed = false


back key will start again activity main also if i have finished it
home button will return to the same activity it was by leaving it
 

ilan

Expert
Licensed User
Longtime User
can i make usercalosed = false also with the back key? because i dont want to return to the 2nd activity, the activity where i pressed back button the leaved the app

is this possible?
 

LucaMs

Expert
Licensed User
Longtime User
Even for me, this is not clear, however, I tell you what I would do.

I might "disable" always the "hardware" back key (ALSO because I read that it will no longer be supported, but I could be wrong) and I would use a button (or whatever) for navigation.

Also, I would not use the Main just for the logo: I would use your second Activity instead of the Main, by superimposing upon it a splash screen (a panel, setting it to visible/invisible).

(Do you want to set the variable UserClosed? I think this is not possible.).
 

ilan

Expert
Licensed User
Longtime User
ok thanx lucas.

after understanding a little bit more now i will see how i can fix my apps and rmove Exitapplication because erel said this is not right to do

but do you know why i should not call activity.finish in activity.pause? and if i wont then where should i call activity.finish?
i want to start activity 2 from activity 1 and close activity1 so i wont be called again

i cannot put after:

Sub b1_click
startactivity("menu")
Activity.finish >>> this wont be read right? because i start activity menu before it
end sub

and like this

sub b1_click
activity.finish
startactivity("menu") >>> this wont be read because i finished the activity before this line
end sub

so where should i call activity.finish? (my only solution is in activity_pause!) and i need to finish activity main because i dont want to show the logo again if user press back button and i want to use the back button to go back to the android platform
 

LucaMs

Expert
Licensed User
Longtime User
As always, I'm not sure, without doing some tests (and now I'm not doing).

If the user presses Home, when he comes back to your app, it should return to the current Activity automatically, I think.

Do not ask me why, but I think that:

sub b1_click
startActivity ("menu")
Activity.finish '<--- this will be executed
end sub

Activity.Finish should be used to close the current activity and return to the previous one, I think. Where to put it depends on the functionality of your activity.
 

ilan

Expert
Licensed User
Longtime User
this is what happens

home button > returns to current (last opened) activity | also userclosed = false
back button > returns to main | also userclosed = true

so i guess the app ask if userclosed the app if yes returns to main and start the all app again but if not (like phone call, home button,..) then back to current

so if i could exit my app and Userclosed will be false i will come back to current activity.

**
about the activity.finish, i just put it in activity_pause event and everything is ok but erel said its not correct to do and i would like to understand why

i guess erel is now in an other univers (IOS) so when he wil land back on B4A he will maybe answer me that question (i hope) :)
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
but if i press back button and the return to app it should return to activity menu like on the home button it does, or am i wrong?
Yes, you are wrong. When the back key is pressed the activity is destroyed and removed from the stack. Later when the user returns to your app the main activity is created (and FirstTime is false if the process was not killed).

The solution is very simple. Just call StartActivity(menu) if FirstTime is false.
 

ilan

Expert
Licensed User
Longtime User
ok thank you i learned something new today

the difference between back key and home key

is there a way to exit my app with the back key but dont remove it from the stack?
 

Kwame Twum

Active Member
Licensed User
Longtime User
Hi everyone, I have a fair understanding of the LifeCycle concept, but my app is behaving strangely...
I'm using RSCrop Library(by @XverhelstX) to load an image from the gallery and crop it. This image would then be set as the background of an imageview.
These are the steps I've already proposed to go about:
  1. User taps on the ImageView
  2. RSCrop Starts the gallery (Activity Pauses)
  3. Image is selected and cropped
  4. Activity resumes and the cropped image is set as the background of an imageview.
However, my paused Activity most often never resumes and sometimes, even kills the entire app. The Cropped Sub is sometimes never reached/called. I think the OS might be killing it or something else is wrong, but I'm not sure why...

Need help :rolleyes:

Testing Devices:
  1. Emulator (Android 2.3.3) - Happens once in a while
  2. Samsung Galaxy Ace 3 (Android 4.1.2) - Happens almost everytime :(
  3. Sony Xperia Sola (Android 4.4.2) - Rarely happens
 
Top