Project: A Two-Screen Android App
Everything you have learned in this tutorial — Activities, layouts, the lifecycle, the Manifest, resources, Intents, and logging — converges in this final lesson. You will build a complete, working Android app that has two screens: a Home screen where the user types their name, and a Greeting screen that displays a personalised welcome message. The navigation between them uses an explicit Intent carrying an Extra, exactly as a professional Android developer would write it.
What you will practise: creating a second Activity class and layout, declaring it in the Manifest, launching it with startActivity(), passing data via Intent extras, reading that data in the receiving Activity, and wiring up a back-navigation button — all in Java.
App Architecture at a Glance
The app has exactly two screens:
- MainActivity — a text field (
EditText) and a "Say Hello" button (Button).
- GreetingActivity — a
TextView showing "Hello, name!" and a "Go Back" button.
Data flows in one direction: MainActivity reads the name from the EditText, bundles it into an Intent extra, and starts GreetingActivity. The greeting screen unpacks the extra and renders it. No database, no network — clean and focused on navigation.
Step 1 — The Main Layout (activity_main.xml)
Open res/layout/activity_main.xml and replace its content with a simple vertical LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="32dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/prompt_name"
android:textSize="18sp"
android:layout_marginBottom="16dp" />
<EditText
android:id="@+id/etName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint_name"
android:inputType="textPersonName"
android:layout_marginBottom="24dp" />
<Button
android:id="@+id/btnSayHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn_say_hello" />
</LinearLayout>
Step 2 — The Greeting Layout (activity_greeting.xml)
Create a new layout file: right-click res/layout → New → Layout Resource File → name it activity_greeting. Use this content:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="32dp">
<TextView
android:id="@+id/tvGreeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textStyle="bold"
android:layout_marginBottom="32dp" />
<Button
android:id="@+id/btnGoBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn_go_back" />
</LinearLayout>
Step 3 — String Resources (res/values/strings.xml)
All user-visible text lives in strings.xml — never hardcode strings in layouts or Java code:
<resources>
<string name="app_name">TwoScreenApp</string>
<string name="prompt_name">Enter your name:</string>
<string name="hint_name">Your name</string>
<string name="btn_say_hello">Say Hello</string>
<string name="btn_go_back">Go Back</string>
<string name="greeting_format">Hello, %1$s!</string>
</resources>
The %1$s placeholder is used with getString(R.string.greeting_format, name) in Java to produce the formatted greeting.
Step 4 — MainActivity.java
This Activity reads the name and fires the Intent:
package com.example.twoscreenapp;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
// Key constant for the Intent extra — define it here so both
// activities agree on the same string without duplication
public static final String EXTRA_NAME = "com.example.twoscreenapp.EXTRA_NAME";
private EditText etName;
private Button btnSayHello;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etName = findViewById(R.id.etName);
btnSayHello = findViewById(R.id.btnSayHello);
btnSayHello.setOnClickListener(v -> launchGreeting());
}
private void launchGreeting() {
String name = etName.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
Toast.makeText(this, "Please enter your name", Toast.LENGTH_SHORT).show();
return;
}
// Build an explicit Intent targeting GreetingActivity
Intent intent = new Intent(this, GreetingActivity.class);
intent.putExtra(EXTRA_NAME, name); // attach the name as an extra
startActivity(intent); // launch the second screen
}
}
Define extra keys as public static final String constants on the sending Activity. The receiving Activity references them as MainActivity.EXTRA_NAME instead of typing a raw string — a typo in a raw string silently returns null, whereas a compile error on a constant is caught immediately.
Step 5 — GreetingActivity.java
Create the second Activity: right-click the package → New → Java Class → name it GreetingActivity. Extend AppCompatActivity:
package com.example.twoscreenapp;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class GreetingActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_greeting);
// Retrieve the name that MainActivity put into the Intent
String name = getIntent().getStringExtra(MainActivity.EXTRA_NAME);
// Format and display the greeting
TextView tvGreeting = findViewById(R.id.tvGreeting);
tvGreeting.setText(getString(R.string.greeting_format, name));
// "Go Back" finishes this Activity, revealing MainActivity underneath
Button btnGoBack = findViewById(R.id.btnGoBack);
btnGoBack.setOnClickListener(v -> finish());
}
}
Calling finish() destroys GreetingActivity and pops it from the back stack, returning the user to MainActivity — exactly what the system Back button does. You do not start a new instance of MainActivity; that would create a duplicate and break the back stack.
Never call startActivity(new Intent(this, MainActivity.class)) from a back button. This pushes a fresh MainActivity onto the stack instead of returning to the existing one. Always use finish() to go back one level.
Step 6 — Registering GreetingActivity in the Manifest
Every Activity must be declared in AndroidManifest.xml. Android Studio's wizard adds it automatically when you use New → Activity, but if you created the class manually you must add it yourself:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.twoscreenapp">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:theme="@style/Theme.TwoScreenApp">
<!-- Entry-point Activity -->
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Second screen — no intent-filter needed; launched explicitly -->
<activity
android:name=".GreetingActivity"
android:exported="false"
android:parentActivityName=".MainActivity" />
</application>
</manifest>
The android:parentActivityName attribute tells the system and the action bar's Up (←) button that MainActivity is the logical parent. It is good practice even though our explicit "Go Back" button already handles navigation.
Step 7 — Run and Verify
Launch the app on the emulator or a device. The expected behaviour is:
- The home screen appears with an
EditText and a "Say Hello" button.
- Leaving the field empty and tapping the button shows a
Toast — no navigation occurs.
- Typing a name and tapping "Say Hello" navigates to the greeting screen showing "Hello, name!".
- Tapping "Go Back" or the system Back button returns to the home screen.
- The name field retains its value because
MainActivity was never destroyed — it is merely paused and stopped while GreetingActivity is visible.
Lifecycle Review
When the user navigates forward: MainActivity.onPause() → MainActivity.onStop() → GreetingActivity.onCreate() → GreetingActivity.onStart() → GreetingActivity.onResume(). When they return: GreetingActivity.onPause() → GreetingActivity.onStop() → GreetingActivity.onDestroy() → MainActivity.onRestart() → MainActivity.onStart() → MainActivity.onResume(). MainActivity is never fully destroyed; it resumes with its view state intact.
Summary
You have built a complete two-screen Android app in Java. The key patterns to carry forward are: declare every Activity in the Manifest, use explicit Intents with typed extra-key constants to pass data, call finish() (not a new Intent) to go back, and keep all user-facing strings in strings.xml. These fundamentals scale directly to apps with ten or twenty screens — the mechanics are identical regardless of complexity.