# Activity
An Activity represents a single screen with a user interface(UI). An Android App may have more than one Activity, for example, An email App can have one activity to list all the emails, another activity to show email contents, yet another activity to compose new email. All the activities in an App work together to create perfect user experience.
# Activity launchMode
Launch mode defines the behaviour of new or existing activity in the task.
There are possible launch modes:
- standard
- singleTop
- singleTask
- singleInstance
It should be defined in android manifest in <activity/>
element as android:launchMode
attribute.
<activity
android:launchMode=["standard" | "singleTop" | "singleTask" | "singleInstance"] />
# Standard:
Default value. If this mode set, new activity will always be created for each new intent. So it's possible to get many activities of same type. New activity will be placed on the top of the task. There is some difference for different android version: if activity is starting from another application, on androids <= 4.4 it will be placed on same task as starter application, but on >= 5.0 new task will be created.
# SingleTop:
This mode is almost the same as standard
. Many instances of singleTop activity could be created. The difference is, if an instance of activity already exists on the top of the current stack, onNewIntent()
will be called instead of creating new instance.
# SingleTask:
Activity with this launch mode can have only one instance in the system. New task for activity will be created, if it doesn't exist. Otherwise, task with activity will be moved to front and onNewIntent
will be called.
# SingleInstance:
This mode is similar to singleTask
. The difference is task that holds an activity with singleInstance
could have only this activity and nothing more. When singleInstance
activity create another activity, new task will be created to place that activity.
# Exclude an activity from back-stack history
Let there be Activity B
that can be opened, and can further start more Activities. But, user should not encounter it when navigating back in task activities.
The simplest solution is to set the attribute noHistory
to true
for that <activity>
tag in AndroidManifest.xml
:
<activity
android:name=".B"
android:noHistory="true">
This same behavior is also possible from code if B
calls finish()
before starting the next activity:
finish();
startActivity(new Intent(context, C.class));
Typical usage of noHistory
flag is with "Splash Screen" or Login Activities.
# Android Activity LifeCycle Explained
Assume an application with a MainActivity which can call the Next Activity using a button click.
public class MainActivity extends AppCompatActivity {
private final String LOG_TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "calling onCreate from MainActivity");
}
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "calling onStart from MainActivity");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "calling onResume from MainActivity");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "calling onPause from MainActivity");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "calling onStop from MainActivity");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "calling onDestroy from MainActivity");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "calling onRestart from MainActivity");
}
public void toNextActivity(){
Log.d(LOG_TAG, "calling Next Activity");
Intent intent = new Intent(this, NextActivity.class);
startActivity(intent);
} }
and
public class NextActivity extends AppCompatActivity {
private final String LOG_TAG = NextActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
Log.d(LOG_TAG, "calling onCreate from Next Activity");
}
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "calling onStart from Next Activity");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOG_TAG, "calling onResume from Next Activity");
}
@Override
protected void onPause() {
super.onPause();
Log.d(LOG_TAG, "calling onPause from Next Activity");
}
@Override
protected void onStop() {
super.onStop();
Log.d(LOG_TAG, "calling onStop from Next Activity");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "calling onDestroy from Next Activity");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "calling onRestart from Next Activity");
} }
When app is first created
D/MainActivity: calling onCreate from MainActivity
D/MainActivity: calling onStart from MainActivity
D/MainActivity: calling onResume from MainActivity
are called
When screen sleeps
08:11:03.142 D/MainActivity: calling onPause from MainActivity
08:11:03.192 D/MainActivity: calling onStop from MainActivity
are called. And again when it wakes up
08:11:55.922 D/MainActivity: calling onRestart from MainActivity
08:11:55.962 D/MainActivity: calling onStart from MainActivity
08:11:55.962 D/MainActivity: calling onResume from MainActivity
are called
Case1:
When Next Activity is called from Main Activity
D/MainActivity: calling Next Activity
D/MainActivity: calling onPause from MainActivity
D/NextActivity: calling onCreate from Next Activity
D/NextActivity: calling onStart from Next Activity
D/NextActivity: calling onResume from Next Activity
D/MainActivity: calling onStop from MainActivity
When Returning back to the Main Activity from Next Activity using back button
D/NextActivity: calling onPause from Next Activity
D/MainActivity: calling onRestart from MainActivity
D/MainActivity: calling onStart from MainActivity
D/MainActivity: calling onResume from MainActivity
D/NextActivity: calling onStop from Next Activity
D/NextActivity: calling onDestroy from Next Activity
Case2:
When Activity is partially obscured (When overview button is pressed) or When app goes to background and another app completely obscures it
D/MainActivity: calling onPause from MainActivity
D/MainActivity: calling onStop from MainActivity
and when the app is back in the foreground ready to accept User inputs,
D/MainActivity: calling onRestart from MainActivity
D/MainActivity: calling onStart from MainActivity
D/MainActivity: calling onResume from MainActivity
are called
Case3:
When an activity is called to fulfill implicit intent and user has make a selection. For eg., when share button is pressed and user has to select an app from the list of applications shown
D/MainActivity: calling onPause from MainActivity
The activity is visible but not active now. When the selection is done and app is active
D/MainActivity: calling onResume from MainActivity
is called
Case4:
When the app is killed in the background(to free resources for another foreground app), onPause(for pre-honeycomb device) or onStop(for since honeycomb device) will be the last to be called before the app is terminated.
onCreate and onDestroy will be called utmost once each time the application is run. But the onPause, onStop, onRestart, onStart, onResume maybe called many times during the lifecycle.
# End Application with exclude from Recents
First define an ExitActivity in the AndroidManifest.xml
<activity
android:name="com.your_example_app.activities.ExitActivity"
android:autoRemoveFromRecents="true"
android:theme="@android:style/Theme.NoDisplay" />
Afterwards the ExitActivity-class
/**
* Activity to exit Application without staying in the stack of last opened applications
*/
public class ExitActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Utils.hasLollipop()) {
finishAndRemoveTask();
} else if (Utils.hasJellyBean()) {
finishAffinity();
} else {
finish();
}
}
/**
* Exit Application and Exclude from Recents
*
* @param context Context to use
*/
public static void exitApplication(ApplicationContext context) {
Intent intent = new Intent(context, ExitActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(intent);
}
}
# Presenting UI with setContentView
Activity class takes care of creating a window for you in which you can place your UI with setContentView
.
There are three setContentView
methods:
setContentView(int layoutResID)
- Set the activity content from a layout resource.setContentView(View view)
- Set the activity content to an explicit view.setContentView(View view, ViewGroup.LayoutParams params)
- Set the activity content to an explicit view with provided params.
When setContentView
is called, this view is placed directly into the activity's view hierarchy. It can itself be a complex view hierarchy.
# Examples
# Set content from resource file:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello" />
</FrameLayout>
Set it as content in activity:
public final class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The resource will be inflated,
// adding all top-level views to the activity.
setContentView(R.layout.main);
}
}
Set content to an explicit view:
public final class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Creating view with container
final FrameLayout root = new FrameLayout(this);
final TextView text = new TextView(this);
text.setText("Hello");
root.addView(text);
// Set container as content view
setContentView(root);
}
}
# Clear your current Activity stack and launch a new Activity
If you want to clear your current Activity stack and launch a new Activity (for example, logging out of the app and launching a log in Activity), there appears to be two approaches.
1. Target (API >= 16)
Calling finishAffinity()
from an Activity
2. Target (11 <= API < 16)
Intent intent = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
# Up Navigation for Activities
Up navigation is done in android by adding android:parentActivityName=""
in Manifest.xml to the activity tag. Basically with this tag you tell the system about the parent activity of a activity.
How is it done?
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".SkillSchoolApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ui.activities.SplashActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.activities.MainActivity" />
<activity android:name=".ui.activities.HomeActivity"
android:parentActivityName=".ui.activities.MainActivity/> // HERE I JUST TOLD THE SYSTEM THAT MainActivity is the parent of HomeActivity
</application>
Now when i will click on the arrow inside the toolbar of HomeActivity it will take me back to the parent activity.
Java Code
Here i will write the appropriate java code required for this functionality.
public class HomeActivity extends AppCompatActivity {
@BindView(R.id.toolbar)
Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
ButterKnife.bind(this);
//Since i am using custom tool bar i am setting refernce of that toolbar to Actionbar. If you are not using custom then you can simple leave this and move to next line
setSupportActionBar(toolbar);
getSupportActionBar.setDisplayHomeAsUpEnabled(true); // this will show the back arrow in the tool bar.
}
}
If you run this code you will see when you press back button it will take you back to MainActivity. For futher understanding of Up Navigation i would recommend reading docs (opens new window)
You can more customize this behaviour upon your needs by overriding
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this); // Here you will write your logic for handling up navigation
return true;
}
return super.onOptionsItemSelected(item);
}
Simple Hack
This is simple hack which is mostly used to navigate to parent activity if parent is in backstack. By calling onBackPressed()
if id is equal to android.R.id.home
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
# Syntax
# Parameters
Parameter | Details |
---|---|
Intent (opens new window) | Can be used with startActivity (opens new window) to launch an Activity |
Bundle (opens new window) | A mapping from String keys to various Parcelable (opens new window) values. |
Context (opens new window) | Interface to global information about an application environment. |
# Remarks
An Activity (opens new window) is an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map. Each activity is given a window in which to draw its user interface. The window typically fills the screen, but may be smaller than the screen and float on top of other windows.