Chapter03 Life Cycle - Publish
Chapter03 Life Cycle - Publish
MOBILE DEVELOPMENT
APPLICATION’S LIFE CYCLE
Each core component provides a particular type of functionality and has a distinct lifecycle. Applications must designate one activity as their main
task or entry point. That activty is the first to be executed
when the app is launched.
A lifecycle defines how the component is created, transitioned, and destroyed.
An activity may transfer control and data to another
There are four type of core components activity through an interprocess communication protocol
called intents
◦ Activities
◦ Services For example, a login activity may show a screen to enter
username and password. After clicking a button some
◦ Broadcast Receiver authentication process is applied on the data, and before
the login activity ends some other activity is called.
◦ Content Provider
Examples:
◦ Your background GPS service could be set to quietly run in the background detecting location information from
satellites, phone towers or wi-fi routers.
◦ The service could periodically broadcast location coordinates to any app listening for that kind of data.
◦ An application may opt for binding to the running GPS service and use the data that it supplies.
ANATOMY OF ANDROID APPLICATIONS ANATOMY OF ANDROID APPLICATIONS
(Android’s core components – broadcast receiver) (Android’s core components – content provider)
A broadcast receiver is a dedicated listener that waits for a triggering system-wide message to do some work. The message A content provider is a data-centric service making persistent datasets available to any applications.
could be something like low-battery, wi-fi connection available, earth-quakes in California, speed-camera nearby.
Common global datasets include contacts, pictures, messages, audio files, emails.
Broadcast receivers do not display a user interface.
The global datasets are stored in an SQLite database (however developer doesn’t have to be an SQL expert)
They typically register with the system by means of a filter acting as a key. When the broadcasted message matches the
key the receiver is activated. The content provider class offers a standard set of parametric methods to enable other applications to retrieve, delete, update,
and insert data items.
A broadcast receiver could respond by either executing a specific activity or use the notification mechanism to request the
user‘s attention. Content provider is a wrapper hiding the actual physical data. Users interact with their data through a common object interface.
after receiving an
ORANGE message delete
Send an ORANGE signal Cloud
dataset
Waiting. My filter only update
accepts ORANGE signals.
Ignoring all others.
@Override
Activity n – 1 protected void onStop() {super.onStop(); …}
…
@Override
Activity 2 Removed to free resources protected void onDestroy() { super.onDestroy(); …}
}
Activity 1
COMPONENT’S LIFE CYCLE COMPONENT’S LIFE CYCLE
(Activity states and callback (Activity state: running & paused & stopped)
methods) Your activity is active or running when it is in foreground of screen (seating on top of the activity stack)
An activity has essentially three phases: This is the activity that has “focus” and its graphical interface is responsive to the user’s interactions.
◦ 1. It is active or running
◦ 2. It is paused or Your Activity is paused if it has lost focus but is still visible to the user.
◦ 3. It is stopped . That is, another activity seats on top and new activity either is transparent or doesn't cover full screen.
Moving from one state to the other is A paused activity is alive (maintaining its state information and attachment to the window manager).
accomplished by means of the callback methods Paused activities can be killed by the system when available memory becomes extremely low.
listed on the edges of the diagram
Your Activity is stopped if it is completely obscured by another activity.
Although stopped, it continues to retain all its state information.
It is no longer visible to the user ( its window is hidden, and its life cycle could be terminated at any point by the system if
the resources that it holds are needed elsewhere).
http://developer.android.com/training/basics/activity-lifecycle/starting.html
◦ 17. Use the onResume method to add the following fragment Foreground
cycle
SharedPreferences myFile = getSharedPreferences("myFile1", Activity.MODE_PRIVATE);
if ( (myFile != null) && (myFile.contains("mydata")) ) {
String temp = myFile.getString("mydata", "***");
txtMsg.setText(temp); Visible cycle
}
◦ 18. What happens now with the data previously entered in the text box?
APPLICATION’S LIFE CYCLE APPLICATION’S LIFE CYCLE
(Associating lifecycle events with (Associating lifecycle events with
application’s code) application’s code)
Applications do not need to implement each of the transition methods, Applications do not need to implement each of the transition methods, however
however there are mandatory and recommended states to consider there are mandatory and recommended states to consider
◦ Mandatory ◦ Highly Recommended
◦ onCreate() must be implemented by each activity to do its initial setup. ◦ onPause() should be implemented whenever the application has some important
The method is executed only once on the activity’s lifetime. data to be committed so it could be reused.
◦ This is the first callback method to be executed when an activity is ◦ Called when the system is about to transfer control to another activity. It should
created. be used to safely write uncommitted data and stop any work in progress.
◦ Most of your application’s code is written here. ◦ The next activity waits until completion of this state.
◦ Typically used to initialize the application’s data structures, wire-up UI ◦ Followed either by onResume() if the activity returns back to the foreground, or
view elements (buttons, text boxes, lists) with local Java controls, define by onStop() if it becomes invisible to the user.
listeners’ behavior, etc. ◦ A paused activity could be killed by the system.
◦ It may receive a data Bundle object containing the activity’s previous
state (if any).
◦ Followed by onStart() ⟶ onResume() ….
EXAMPLE EXAMPLE
The following application demonstrates the transitioning of a simple activity through the
(The LifeCycle app – layout )
Android’s sequence of Life-Cycle states. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools” android:id=“@+id/myScreen1”
1. A Toast-msg will be displayed showing the current event’s name. android:layout_width=“fill_parent” android:layout_height=“fill_parent”
android:orientation=“vertical”
2. An EditText box is provided for the user to indicate a background color. tools:context=“.MainActivity”>
<EditText android:id=“@+id/editText1”
3. When the activity is paused the selected background color value is saved to a SharedPreferences android:layout_width=“match_parent”
container. android:layout_height=“wrap_content”
android:hint=“Pick background (red, green, blue, white)”
4. When the application is re-executed the last choice of background color should be applied. android:ems="10" >
5. An EXIT button should be provideD to terminate the app. <requestFocus />
</EditText>
6. You are asked to observe the sequence of messages displayed when the application: <Button android:id=“@+id/button1”
android:layout_width=“wrap_content”
6.1. Loads for the first time android:layout_height=“wrap_content”
6.2. Is paused after clicking HOME button android:text=“Exit” />
<TextView android:id=“@+id/textView1”
6.3. Is re-executed from launch-pad android:layout_width=“wrap_content”
6.4. Is terminated by pressing BACK and its own EXIT button android:layout_height=“wrap_content”
android:text=“spy box - try clicking HOME and BACK” />
6.5. Re-executed after a background color is set </LinearLayout>
EXAMPLE EXAMPLE
(The LifeCycle app – code: MainActivity.java ) (The LifeCycle app – code: MainActivity.java )
@Override @Override
package csu.matos.lifecycle; //set GUI listeners, watchers,...
protected void onDestroy() { protected void onStart() { super.onStart();
import java.util.Locale; btnExit.setOnClickListener(new OnClickListener() {
super.onDestroy(); //if appropriate, change background color to chosen value
. . . //other libraries omitted for brevity @Override
Toast.makeText(context, “onDestroy”, duration).show(); updateMeUsingSavedStateData();
public class MainActivity extends Activity { public void onClick(View v) { finish();}
} Toast.makeText(context, “onStart”, duration).show();
//class variables });
@Override }
private Context context; //observe (text) changes made to EditText box (color selection)
protected void onPause() { @Override
private int duration = Toast.LENGTH_SHORT; txtColorSelected.addTextChangedListener(new TextWatcher() {
super.onPause(); protected void onStop() { super.onStop(); Toast.makeText(context, “onStop”, duration).show(); }
//PLUMBING: Pairing GUI controls with Java objects @Override
//save state data (background color) for future use private void setBackgroundColor(String chosenColor, LinearLayout myScreen) {
private Button btnExit; public void onTextChanged(CharSequence s, int start, int before, int count) { /* nothing TODO, needed by interface */ }
String chosenColor = txtSpyBox.getText().toString(); //hex color codes: 0xAARRGGBB AA:transp, RR red, GG green, BB blue
private EditText txtColorSelected; @Override
saveStateData(chosenColor); if (chosenColor.contains(“red”)) myScreen.setBackgroundColor(0xffff0000); //Color.RED
private TextView txtSpyBox; public void beforeTextChanged(CharSequence s, int start, int count, int after) { /* nothing TODO, needed by interface */ }
Toast.makeText(context, “onPause”, duration).show(); if (chosenColor.contains(“green”)) myScreen.setBackgroundColor(0xff00ff00); //Color.GREEN
private LinearLayout myScreen; @Override
} if (chosenColor.contains(“blue”)) myScreen.setBackgroundColor(0xff0000ff); //Color.BLUE
private String PREFNAME = “myPrefFile1”; public void afterTextChanged(Editable s) {
@Override if (chosenColor.contains(“white”)) myScreen.setBackgroundColor(0xffffffff); //Color.WHITE
@Override //set background to selected color
protected void onRestart() { } //setBackgroundColor
protected void onCreate(Bundle savedInstanceState) { String chosenColor = s.toString().toLowerCase(Locale.US);
super.onRestart(); private void saveStateData(String chosenColor) {
super.onCreate(savedInstanceState); txtSpyBox.setText(chosenColor);
Toast.makeText(context, “onRestart”, duration).show(); //this is a little <key,value> table permanently kept in memory
//display the main screen setBackgroundColor(chosenColor, myScreen);
} SharedPreferences myPrefContainer = getSharedPreferences(PREFNAME, Activity.MODE_PRIVATE);
setContentView(R.layout.activity_main); }
@Override //pair <key,value> to be stored represents our 'important' data
//wiring GUI controls and matching Java objects });
protected void onResume() { SharedPreferences.Editor myPrefEditor = myPrefContainer.edit();
txtColorSelected = (EditText)findViewById(R.id.editText1); //show the current state's name
super.onResume(); String key = “chosenBackgroundColor”, value = txtSpyBox.getText().toString();
btnExit = (Button) findViewById(R.id.button1); context = getApplicationContext();
Toast.makeText(context, “onResume”, duration).show(); myPrefEditor.putString(key, value);
txtSpyBox = (TextView)findViewById(R.id.textView1); Toast.makeText(context, "onCreate", duration).show();
} myPrefEditor.commit();
myScreen = (LinearLayout)findViewById(R.id.myScreen1); } //onCreate
}//saveStateData
EXAMPLE EXAMPLE
(The LifeCycle app – code: MainActivity.java ) (The LifeCycle app – code: MainActivity.java )
private void updateMeUsingSavedStateData() {
// (in case it exists) use saved data telling backg color
SharedPreferences myPrefContainer = getSharedPreferences(PREFNAME, Activity.MODE_PRIVATE);
String key = “chosenBackgroundColor”;
String defaultValue = “white”;
if (( myPrefContainer != null ) && myPrefContainer.contains(key)){
String color = myPrefContainer.getString(key, defaultValue);
setBackgroundColor(color, myScreen);
}
}//updateMeUsingSavedStateData
} //Activity
EXAMPLE
(The LifeCycle app – code: MainActivity.java ) APPENDIX
User selects a green background and clicks the HOME key. When the app is paused the user’s selection is Using Bundles to save/restore State Values
saved, the app is still active, but it is not visible. @Override
public void onCreate(Bundle savedInstanceState) {
...
if ( savedInstanceState != null )
String someStrValue = savedInstanceState.getString(“STR_KEY”, “Default”);
...
}
@Override
public void onSaveInstanceState(Bundle outState) {
...
outState.putString(“STR_KEY”, “blah blah blah”);
super.onSaveInstanceState(myBundle);
...
}
Note: This approach works well when Android kills the app (like in a device-rotation event), however; it will not create
the state bundle when the user kills the app (eg. pressing BackButton). Hint: It is a better practice to save state using
SharedPreferences in the onPause( ) method.
APPENDIX APPENDIX
Use the onCreate method to initialize a control variable with the original device’s orientation. During onPause compare the current
The function below allows to obtain the current ORIENTATION of the device as NORTH(0), orientation with its original value; if they are not the same then the device was rotated.
WEST(1), SOUTH(2) and EAST(3). int originalOrientation; //used to detect orientation change
@Override
private int getOrientation(){ protected void onCreate(Bundle savedInstanceState) {
// the TOP of the device points to [0:North, 1:West, 2:South, 3:East] ...
Display display = ((WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); setContentView(R.layout.activity_main);
display.getRotation(); originalOrientation = getOrientation();
return display.getRotation(); ...
}
}
@Override
top North: 0 protected void onPause() {
super.onPause();
if( getOrientation() != originalOrientation ){
West: 1 East: 3 // Orientation changed - phone was rotated
// put a flag in outBundle, call onSaveInstanceState(…)
top top }else {
// no orientation change detected in the session
}
}
South: 2 top