2.1: Create and Start Activities

Contents:

An activity represents a single screen in your app with which your user can perform a single, focussed task such as dial the phone, take a photo, send an email, or view a map. Activities are usually presented to the user as full-screen windows.

An app usually consists of multiple activities that are loosely bound to each other. Typically, one activity in an application is specified as the "main" activity, which is presented to the user when the app is launched. Each activity can then start other activities in order to perform different actions.

Each time a new activity starts, the previous activity is stopped, but the system preserves the activity in a stack (the "back stack"). When a new activity starts, that new activity is pushed onto the back stack and takes user focus. The back stack abides to the basic "last in, first out" stack mechanism, so, when the user is done with the current activity and presses the Back button, that current activity is popped from the stack (and destroyed) and the previous activity resumes.

Android activities are started or activated with an intent. Intents are asynchronous messages that you can can use in your activity to request an action from another activity (or other app component). You use intents to start one activity from another and to pass data between activities.

There are two kinds of intents: explicit and implicit. An explicit intent is one in which you know the target of that intent, that is, you already know the fully-qualified class name of that specific activity. An implicit intent is one in which you do not have the name of the target component, but have a general action to perform. In this practical you'll learn about explicit intents. You'll find out about implicit intents in a later practical.

What you should already KNOW

From the previous practicals, you should be able to:

  • Create and run apps in Android Studio.
  • Create and edit UI elements with the graphical Layout Editor, or directly in an XML layout file.
  • Add onClick functionality to a button.

What you will LEARN

You will learn to:

  • Create a new activity in Android studio.
  • Define parent and child activities for "Up" navigation.
  • Start activities with explicit intents.
  • Pass data between activities with intent extras.

What you will DO

In this practical, you will:

  • Create a new Android app with two activities.
  • Pass some data (a string) from the main activity to the second using an intent, and display that data in the second activity.
  • Send a second different bit of data back to the main activity, also using intents.

App Overview

In this chapter you will create and build an app called TwoActivities that, unsurprisingly, contains two activities. This app will be built in three stages.

In the first stage, create an app whose main activity contains only one button (Send). When the user clicks this button, your main activity uses an intent to start the second activity. Main activity launches second activity

In the second stage, you'll add an EditText view to the main activity. The user enters a message and clicks Send. The main activity uses an intent to both start the second activity, and to send the user's message to the that activity. The second activity displays the message it received. Main Activity sends a message to second activity

In final stage of the TwoActivities app, add an EditText view and a Reply button to the second activity. The user can now type a reply message and click Reply, and the reply is displayed on the main activity. At this point, use an intent here to pass the reply message back from the second activity to the main activity. Second activity sends a reply back to main activity

Task 1. Create the TwoActivities project

In this task you'll set up the initial project with a main activity, define the layout, and define a skeleton method for the onClick button event.

1.1 Create the TwoActivities project

  1. Start Android Studio and create a new Android Studio project.

    Call your application "Two Activities" and change the company domain to "android.example.com." Choose the same Minimum SDK that you used in the previous projects.

  2. Choose Empty Activity for the project template. Click Next.
  3. Accept the default activity name (MainActivity). Make sure the Generate Layout file box is checked. Click Finish.

1.2 Define the layout for the main activity

  1. Open res/layout/activity_main.xml. In the Layout Editor, click the Text tab at the bottom of the screen and change the root view group to RelativeLayout, as you've done in previous exercises.
  2. Click the Design tab at the bottom of the screen and delete the TextView that says "Hello World."
  3. Add a Button to the layout in any position.
  4. Switch to the XML Editor (click the Text tab) and modify these attributes in the Button:

    Attribute Value
    android:id "@+id/button_main"
    android:layout_width wrap_content
    android:layout_height wrap_content
    android:layout_alignParentRight "true"
    android:layout_alignParentBottom "true"
    android:layout_alignParentEnd "true"
    android:text "Send"
    android:onClick "launchSecondActivity"

    This may generate an error that "Method launchSecondActivity is missing in MainActivity." Please ignore this error for now. It will be addressed it in the next task.

  5. Place the cursor on the word"Send".
  6. Press Alt-Enter (Option-Enter on the Mac) and select Extract string resources.
  7. Set the Resource name to button_main and click OK.

    This creates a string resource in the values/res/string.xml file, and the string in your code is replaced with a reference to that string resource.

  8. Choose Code > Reformat Code to format the XML code, if necessary.
  9. Preview the layout of the main activity using the Layout Editor. The layout should look like this: Main activity layout (first stage)

Solution code: Depending on your version of Android Studio, your code will look something like the following.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.android.twoactivities.MainActivity">
    <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/button_main"
       android:id="@+id/button_main"
       android:layout_alignParentBottom="true"
       android:layout_alignParentRight="true"
       android:layout_alignParentEnd="true"
       android:onClick="launchSecondActivity"/>
</RelativeLayout>

1.3 Define the button action

In this task,you will implement the onClick method you defined in the layout.

  1. In the XML Editor, place the cursor on the word"launchSecondActivity".
  2. Press Alt-Enter (Option-Enter on the Mac) and select Create 'launchSecondActivity(View)' in 'MainActivity.

    The MainActivity.java files opens, and Android Studio generates a skeleton method for the onClick handler.

  3. Inside launchSecondActivity, add a log statement that says "Button Clicked!"

    Log.d(LOG_TAG, "Button clicked!");
    

    LOG_TAG will show as red. The definitions for that variable will be added in a later step.

  4. Place the cursor on the word "Log" and press Alt-Enter (Option-Enter on the Mac). Android Studio adds an import statement for android.util.Log.
  5. At the top of the class, add a constant for the LOG_TAG variable:

    private static final String LOG_TAG =
        MainActivity.class.getSimpleName();
    

    This constant uses the name of the class itself as the tag.

  6. Run your app. When you click the "Send" button you will see the "Button Clicked!" message in the Android Monitor (logcat). If there's too much output in the monitor, type MainActivity into the search box and the log will only show lines that match that tag.

Solution code:

package com.example.android.twoactivities;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {
   private static final String LOG_TAG = MainActivity.class.getSimpleName();

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
   }

   public void launchSecondActivity(View view) {
       Log.d(LOG_TAG, "Button clicked!");
   }
}

Task 2. Create and launch the second activity

Each new activity you added to your project has its own layout and Java files, separate from those of the main activity. They also have their own <activity> elements in the Android manifest. As with the main activity, new activities you create in Android Studio also extend from the AppCompatActivity class.

All the activities in your app are only loosely connected with each other. However, you can define an activity as a parent of another activity in the AndroidManifest.xml file. This parent-child relationship enables Android to add navigation hints such as left-facing arrows in the title bar for each activity.

Activities communicate with each other (both in the same app and across different apps) with intents. There are two types of intents, explicit and implicit. An explicit intent is one in which the target of that intent is known, that is, you already know the fully-qualified class name of that specific activity. An implicit intent is one in which you do not have the name of the target component, but have a general action to perform. You'll learn about implicit intents in a later practical.

In this task you'll add a second activity to our app, with its own layout. You'll modify the Android manifest to define the main activity as the parent of the second activity. Then you'll modify the onClick event method in the main activity to include an intent that launches the second activity when you click the button.

2.1 Create the second activity

  1. Click the app folder for your project and choose File > New > Activity > Empty Activity.
  2. Name the new activity "SecondActivity." Make sure Generate Layout File is checked, and layout name will be filled in as activity_second.
  3. Click Finish. Android Studio adds both a new activity layout (activity_second) and a new Java file (SecondActivity) to your project for the new activity. It also updates the Android manifest to include the new activity.

2.2 Modify the Android manifest

  1. Open manifests/AndroidManifest.xml.
  2. Find the <activity> element that Android Studio created for the second activity.
    <activity android:name=".SecondActivity"></activity>
    
  3. Add these attributes to the <activity> element:

    Attribute Value
    android:label "Second Activity"
    android:parentActivityName ".MainActivity"

    The label attribute adds the title of the activity to the action bar.

    The parentActivityName attribute indicates that the main activity is the parent of the second activity. This parent activity relationship is used for "upward" navigation within your app. By defining this attribute, the action bar for the second activity will appear with a left-facing arrow to enable the user to navigate "upward" to the main activity.

  4. Place the cursor on "Second Activity" and press Alt-Enter (Option-Enter on the Mac).
  5. Choose Extract string resource, name the resource "activity2_name", and click OK. Android Studio adds a string resource for the activity label.
  6. Add a <meta-data> element inside the <activity> element for the second activity. Use these attributes:

    Attribute Value
    android:name "android.support.PARENT_ACTIVITY"
    android:value "com.example.android.twoactivities.MainActivity"

    The <meta-data> element provides additional arbitrary information about the activity as key-value pairs. In this case these attributes accomplish the same thing as the android:parentActivityName attribute -- they define a relationship between two activities for the purpose of upward navigation. These attributes are required for older versions of Android. android:parentActivityName is only available for API levels 16 and higher.

Solution code:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.android.twoactivities">

   <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">
       <activity android:name=".MainActivity">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
       </activity>
       <activity android:name=".SecondActivity"
           android:label="@string/activity2_name"
           android:parentActivityName=".MainActivity">
           <meta-data
               android:name="android.support.PARENT_ACTIVITY"
               android:value="com.example.android.twoactivities.MainActivity" />
       </activity>
   </application>
</manifest>

2.3 Define the layout for the second activity

  1. Open res/layout/activity_second.xml and change the root view group to RelativeLayout, as you've done in previous exercises.
  2. Add a TextView ("Plain Textview" in the Layout Editor). Give the TextView these attributes:

    Attribute Value
    android:id "@+id/text_header"
    android:layout_width wrap_content
    android:layout_height wrap_content
    android:layout_marginBottom "@dimen/activity_vertical_margin"
    android:text "Message Received"
    android:textAppearance "?android:attr/textAppearanceMedium"
    android:textStyle "bold"

    The value of textAppearance is a special Android theme attribute that defines basic font styles for small, medium, and large fonts. You'll learn more about themes in a later lesson.

  3. Extract the "Message Received" string into a resource named text_header.
  4. Preview the layout in the Layout Editor. The layout should look like this: Second activity layout (first stage)

Solution code: Depending on your version of Android Studio, your code will look something like the following.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context=".SecondActivity">

   <TextView
       android:id="@+id/text_header"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginBottom="@dimen/activity_vertical_margin"
       android:text="@string/text_header"
       android:textAppearance="?android:attr/textAppearanceMedium"
       android:textStyle="bold" />
</RelativeLayout>

2.4 Add an intent to the main activity

In this task you'll add an explicit intent to the main activity. This intent is used to activate the second activity when the Send button is clicked.

  1. Open the Java file for MainActivity (java/com.example.android.twoactivities/MainActivity).
  2. Create a new intent in the launchSecondActivity() method.

    The Intent constructor takes two arguments for an explicit intent: an application Context and the specific component that will receive that intent. Here you should use this as the context, and SecondActivity.class as the specific class.

    Intent intent = new Intent(this, SecondActivity.class);
    
  3. Place the cursor on Intent and press Alt-Enter (Option-Enter on the Mac) to add an import for the Intent class.
  4. Call the startActivity() method with the new intent as the argument.
    startActivity(intent);
    
  5. Run the app.

    When you click the Send button the main activity sends the intent and the Android system launches the second activity. That second activity appears on the screen. To return to the main activity, click the Android Back button at the bottom left of the screen, or you can use the left arrow at the top of the second activity to return to the main activity.

Coding challenge

Note: All coding challenges are optional.

Challenge: What happens if you remove the android:parentActivityName and the <meta-data> elements from the manifest? Make this change and run your app.

Task 3. Send data from the main activity to the second activity

In the last task, you added an explicit intent to the main activity that activated the second activity. You can also use intents to send data from one activity to another.

In this task, you'll modify the explicit intent in the main activity to include additional data (in this case, a user-entered string) in the intent extras. You'll then modify the second activity to get that data back out of the intent extras and display it on the screen.

3.1 Add an EditText to the main activity layout

  1. Open res/layout/activity_main.xml.
  2. Add an EditText view (Plain Text in the Layout Editor.) Give the EditText these attributes:

    Attribute Value
    android:id "@+id/editText_main"
    android:layout_width match_parent
    android:layout_height wrap_content
    android:layout_toLeftOf "@+id/button_main"
    android:layout_toStartOf "@+id/button_main"
    android:layout_alignParentBottom "true"
    android:hint "Enter Your Message Here"
  3. Delete the android:text attribute.
  4. Extract the "Enter Your Message Here" string into a resource named editText_main.

The new layout for the main activity looks like this: Main activity layout (second stage)

Solution code: Depending on your version of Android Studio, your code will look something like the following.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.android.twoactivities.MainActivity">

   <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/button_main"
       android:id="@+id/button_main"
       android:layout_alignParentBottom="true"
       android:layout_alignParentRight="true"
       android:layout_alignParentEnd="true"
       android:onClick="launchSecondActivity"/>

   <EditText
       android:id="@+id/editText_main"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       android:layout_toLeftOf="@+id/button_main"
       android:layout_toStartOf="@+id/button_main"
       android:hint="@string/editText_main" />
</RelativeLayout>

3.2 Add a string to the main activity's intent extras

Your intent object can pass data to the target activity in two ways: in the data field, or in the intent extras. The intent's data is a URI indicating the specific data to be acted on. If the information you want to pass to an activity through an intent is not a URI, or you have more than one piece of information you want to send, you can put that additional information into the intent extras instead.

The intent extras are key/value pairs in a Bundle. A bundle is a collection of data, stored as key/value pairs. To pass information from one activity to another, you put keys and values into the intent extra bundle from the sending activity, and then get them back out again in the receiving activity.

  1. Open java/com.example.android.twoactivities/MainActivity.
  2. Add a public constant at the top of the class to define the key for the intent extra:
    public static final String EXTRA_MESSAGE =
        "com.example.android.twoactivities.extra.MESSAGE";
    
  3. Add a private variable at the top of the class to hold the EditText object. Import the EditText class.
    private EditText mMessageEditText;
    
  4. In the onCreate() method, use findViewByID to get a reference to the EditText instance and assign it to that private variable:
    mMessageEditText = (EditText) findViewById(R.id.editText_main);
    
  5. In the launchSecondActivity() method, just under the new intent, get the text from the EditText as a string:
    String message = mMessageEditText.getText().toString();
    
  6. Add that string to the intent as an extra with the EXTRA_MESSAGE constant as the key and the string as the value:
    intent.putExtra(EXTRA_MESSAGE, message);
    

Solution code:

package com.example.android.twoactivities;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {
   private static final String LOG_TAG = MainActivity.class.getSimpleName();

   public static final String EXTRA_MESSAGE =
"com.example.android.twoactivities.extra.MESSAGE";

   private EditText mMessageEditText;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       mMessageEditText = (EditText) findViewById(R.id.editText_main);
   }

   public void launchSecondActivity(View view) {
       Log.d(LOG_TAG, "Button clicked!");

       Intent intent = new Intent(this, SecondActivity.class);
       String message = mMessageEditText.getText().toString();

       intent.putExtra(EXTRA_MESSAGE, message);
       startActivity(intent);
   }
}

3.3 Add a TextView to the second activity for the message

  1. Open res/layout/activity_second.xml.
  2. Add a second TextView. Give the TextView these attributes:

    Attribute Value
    android:id "@+id/text_message"
    android:layout_width wrap_content
    android:layout_height wrap_content
    android:layout_below "@+id/text_header"
    android:layout_marginLeft "@dimen/activity_horizontal_margin"
    android:layout_marginStart "@dimen/activity_horizontal_margin"
    android:textAppearance "?android:attr/textAppearanceMedium"
  3. Delete the android:text attribute (if it exists).

The new layout for the second activity looks the same as it did in the previous task, because the new TextView does not (yet) contain any text, and thus does not appear on the screen.

Solution code: Depending on your version of Android Studio, your code will look something like the following.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.android.twoactivities.SecondActivity">

   <TextView
       android:id="@+id/text_header"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/text_header"
       android:layout_marginBottom="@dimen/activity_vertical_margin"
       android:textAppearance="?android:attr/textAppearanceMedium"
       android:textStyle="bold"/>

   <TextView
       android:id="@+id/text_message"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@+id/text_header"
       android:layout_marginLeft="@dimen/activity_horizontal_margin"
       android:layout_marginStart="@dimen/activity_horizontal_margin"
       android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

3.4 Modify the second activity to get the extras and display the message

  1. Open java/com.example.android.twoactivities/SecondActivity.
  2. In the onCreate() method, get the intent that activated this activity:
    Intent intent = getIntent();
    
  3. Get the string containing the message from the intent extras using the MainActivity.EXTRA_MESSAGE static variable as the key:
    String message =
        intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
    
  4. Use findViewByID to get a reference to the TextView for the message from the layout (you may need to import the TextView class):
    TextView textView = (TextView) findViewById(R.id.text_message);
    
  5. Set the text of that TextView to the string from the intent extra:
    textView.setText(message);
    
  6. Run the app. When you type a message in the main activity and click Send, the second activity is launched and displays that message.

Solution code:

package com.example.android.twoactivities;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class SecondActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_second);

       Intent intent = getIntent();
       String message =
               intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
       TextView textView = (TextView) findViewById(R.id.text_message);
       textView.setText(message);
   }
}

Task 4. Return data back to the main activity

Now that you have an app that launches a new activity and sends data to it, the final step is to return data from the second activity back to the main activity. You'll also use intents and intent extras for this task.

4.1 Add an EditText and a Button to the second activity layout

  1. Copy the EditText and Button from the main activity layout file and paste them into the second layout.
  2. In the activity_second.xml file, modify the attribute values for both the Button and EditText views. Use these values:

    Old attribute (Button) New attribute (Button)
    android:id="@+id/button_main" android:id="@+id/button_second"
    android:onClick= "launchSecondActivity" android:onClick="returnReply"
    android:text= "@string/button_main" android:text= "@string/button_second"
    Old attribute (EditText) New attribute (EditText)
    android:id="@+id/editText_main" android:id="@+id/editText_second"
    android:layout_toLeftOf= "@+id/button_main" android:layout_toLeftOf= "@+id/button_second"
    android:layout_toStartOf= "@+id/button_main" android:layout_toStartOf= "@+id/button_second"
    android:hint= "@string/editText_main" android:hint= "@string/editText_second"
  3. Open res/values/strings.xml and add string resources for the button text and the hint in the EditText:
    <string name="button_second">Reply</string>
    <string name="editText_second">Enter Your Reply Here</string>
    
  4. In the XML layout editor, place the cursor on "returnReply", press Alt-Enter (Option-Enter on the Mac) and select Create 'returnReply(View)' in 'SecondActivity'.

    The SecondActivity.java files open, and Android Studio generates a skeleton method for the onClick handler. You will implement this method in the next task.

The new layout for the second activity looks like this: Second activity layout (final stage)

Solution code: Depending on your version of Android Studio, your code will look something like the following.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.android.twoactivities.SecondActivity">

   <TextView
       android:id="@+id/text_header"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/text_header"
       android:layout_marginBottom="@dimen/activity_vertical_margin"
       android:textAppearance="?android:attr/textAppearanceMedium"
       android:textStyle="bold"/>

   <TextView
       android:id="@+id/text_message"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@+id/text_header"
       android:layout_marginLeft="@dimen/activity_horizontal_margin"
       android:layout_marginStart="@dimen/activity_horizontal_margin"
       android:textAppearance="?android:attr/textAppearanceMedium" />

   <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/button_second"
       android:id="@+id/button_second"
       android:layout_alignParentBottom="true"
       android:layout_alignParentRight="true"
       android:layout_alignParentEnd="true"
       android:onClick="returnReply"/>

   <EditText
       android:id="@+id/editText_second"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       android:layout_toLeftOf="@+id/button_second"
       android:layout_toStartOf="@+id/button_second"
       android:hint="@string/editText_second" />

</RelativeLayout>

4.2 Create a response intent in the second activity

  1. Open java/com.example.android.twoactivities/SecondActivity.
  2. At the top of the class, add a public constant to define the key for the intent extra:
    public static final String EXTRA_REPLY =     
        "com.example.android.twoactivities.extra.REPLY";
    
  3. Add a private variable at the top of the class to hold the EditText object.
    private EditText mReply;
    
  4. In the onCreate() method, use findViewByID() to get a reference to the EditText instance and assign it to that private variable:
    mReply = (EditText) findViewById(R.id.editText_second);
    
  5. In the returnReply() method, get the text of the EditText as a string:
    String reply = mReply.getText().toString();
    
  6. Create a new intent for the response.
    Note: Do not reuse the intent object you received from the original request. Create a new intent for the response.
    Intent replyIntent = new Intent();
    
  7. Add the reply string from the EditText to the new intent as an intent extra. Since extras are key/value pairs, here the key is EXTRA_REPLY and the the value is the reply:
    replyIntent.putExtra(EXTRA_REPLY, reply);
    
  8. Set the result to RESULT_OK to indicate the response was successful. Result codes (including RESULT_OK and RESULT_CANCELLED) are defined by the Activity class.
    setResult(RESULT_OK,replyIntent);
    
  9. Call finish() to close the activity and return to the main activity.
    finish();
    

Solution code:

package com.example.android.twoactivities;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class SecondActivity extends AppCompatActivity {
   public static final String EXTRA_REPLY =
           "com.example.android.twoactivities.extra.REPLY";

   private EditText mReply;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_second);
       mReply = (EditText) findViewById(R.id.editText_second);

       Intent intent = getIntent();
       String message =
               intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
       TextView textView = (TextView) findViewById(R.id.text_message);
       textView.setText(message);
   }

   public void returnReply(View view) {
       String reply = mReply.getText().toString();

       Intent replyIntent = new Intent();
       replyIntent.putExtra(EXTRA_REPLY, reply);
       setResult(RESULT_OK, replyIntent);
       finish();
   }
}

4.3 Add TextViews to the main activity layout to display the reply

The main activity needs a way to display the reply sent back from the second activity. In this task you'll add TextViews to the main activity layout to display that reply. To make this easier, you will copy the TextViews you used in the second activity.

  1. Copy the two TextViews for the message display from the second activity layout file and paste them into the main layout above the existing EditText and Button views.
  2. Modify the attribute values for both of these new TextViews. Use these values:

    Old attribute (header TextView) New attribute (header TextView)
    android:id="@+id/text_header" android:id="@+id/text_header_reply"
    android:text="@string/text_header" android:text= "@string/text_header_reply"
    Old attribute (message TextView) New attribute (message TextView)
    android:id="@+id/text_message" android:id="@+id/text_message_reply"
    android:layout_below= "@+id/text_header" android:layout_below= "@+id/text_header_reply"
  3. Add the android:visibility attribute to each of the TextViews to make them initially invisible. (Having them visible on the screen, but without any content, can be confusing to the user.) You will make these TextViews visible after the response data is passed back from the second activity.
    android:visibility="invisible"
    
  4. Open res/values/strings.xml and add a string resource for the reply header:
    <string name="text_header_reply">Reply Received</string>
    

The layout for the main activity looks the same as it did in the previous task--although you have added two new TextViews to the layout. However, since you set the TextViews to invisible, they do not appear on the screen.

Solution code: Depending on your version of Android Studio, your code will look something like the following.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.android.twoactivities.MainActivity">
   <TextView
       android:id="@+id/text_header_reply"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/text_header_reply"
       android:visibility="invisible"
       android:layout_marginBottom="@dimen/activity_vertical_margin"
       android:textAppearance="?android:attr/textAppearanceMedium"
       android:textStyle="bold"/>

   <TextView
       android:id="@+id/text_message_reply"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@+id/text_header_reply"
       android:visibility="invisible"
       android:layout_marginLeft="@dimen/activity_horizontal_margin"
       android:layout_marginStart="@dimen/activity_horizontal_margin"
       android:textAppearance="?android:attr/textAppearanceMedium" />

   <Button
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/button_main"
       android:id="@+id/button_main"
       android:layout_alignParentBottom="true"
       android:layout_alignParentRight="true"
       android:layout_alignParentEnd="true"
       android:onClick="launchSecondActivity"/>

   <EditText
       android:id="@+id/editText_main"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentBottom="true"
       android:layout_toLeftOf="@+id/button_main"
       android:layout_toStartOf="@+id/button_main"
       android:hint="@string/editText_main" />
</RelativeLayout>

4.4 Get the reply from the intent extra and display it

When you use an explicit intent to start another activity, you may not expect to get any data back -- you're just activating that activity. In that case, you use startActivity() to start the new activity, as you did earlier in this lesson. If you want to get data back from the activated activity, however, you'll need to start it with startActivityFromResult().

In this task you'll modify the app to start the second activity and expect a result, to extract that return data from the intent, and to display that data in the TextViews you created in the last task.

  1. Open java/com.example.android.twoactivities/MainActivity.
  2. Add a public constant at the top of the class to define the key for a particular type of response you're interested in:
    public static final int TEXT_REQUEST = 1;
    
  3. Add two private variables to hold the reply header and reply TextViews:
    private TextView mReplyHeadTextView;
    private TextView mReplyTextView;
    
  4. In the onCreate() method, use findViewByID to get references from the layout to the reply header and reply TextView. Assign those view instances to the private variables:
    mReplyHeadTextView = (TextView) findViewById(R.id.text_header_reply);
    mReplyTextView = (TextView) findViewById(R.id.text_message_reply);
    
  5. In the launchSecondActivity() method, modify the call to startActivity() to be startActivityForResult(), and include the TEXT_REQUEST key as an argument:
    startActivityForResult(intent, TEXT_REQUEST);
    
  6. Create the onActivityResult() callback method with this signature:
    public void onActivityResult(int requestCode, int resultCode,
        Intent data) {}
    
  7. Inside onActivityResult(), call super.onActivityResult():
    super.onActivityResult(requestCode, resultCode, data);
    
  8. Add code to test for both TEXT_REQUEST (to process the right intent result, in case there are multiple ones) and the RESULT_CODE (to make sure the request was successful):
    if (requestCode == TEXT_REQUEST) {
        if (resultCode == RESULT_OK) {
        }
    }
    
  9. Inside the inner if block, get the intent extra from the response intent (data). Here the key for the extra is the EXTRA_REPLY constant from SecondActivity:
    String reply = data.getStringExtra(SecondActivity.EXTRA_REPLY);
    
  10. Set the visibility of the reply header to true:
    mReplyHeadTextView.setVisibility(View.VISIBLE);
    
  11. Set the reply textview text to the reply, and set its visibility to true:
    mReplyTextView.setText(reply);
    mReplyTextView.setVisibility(View.VISIBLE);
    
  12. Run the app.

    Now, when you send a message to the second activity and get a reply back, the main activity updates to display the reply. Main activity

Solution code:

package com.example.android.twoactivities;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
   private static final String LOG_TAG = MainActivity.class.getSimpleName();

   public static final String EXTRA_MESSAGE =
        "com.example.android.twoactivities.extra.MESSAGE";

   public static final int TEXT_REQUEST = 1;

   private EditText mMessageEditText;
   private TextView mReplyHeadTextView;
   private TextView mReplyTextView;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       mMessageEditText = (EditText) findViewById(R.id.editText_main);
       mReplyHeadTextView = (TextView) findViewById(R.id.text_header_reply);
       mReplyTextView = (TextView) findViewById(R.id.text_message_reply);
   }

   public void launchSecondActivity(View view) {
       Log.d(LOG_TAG, "Button clicked!");

       Intent intent = new Intent(this, SecondActivity.class);
       String message = mMessageEditText.getText().toString();

       intent.putExtra(EXTRA_MESSAGE, message);
       startActivityForResult(intent, TEXT_REQUEST);
   }

   public void onActivityResult(int requestCode, int resultCode,
                                Intent data) {
       super.onActivityResult(requestCode, resultCode, data);

       if (requestCode == TEXT_REQUEST) {
           if (resultCode == RESULT_OK) {
               String reply =
                   data.getStringExtra(SecondActivity.EXTRA_REPLY);

               mReplyHeadTextView.setVisibility(View.VISIBLE);
               mReplyTextView.setText(reply);
               mReplyTextView.setVisibility(View.VISIBLE);
           }
       }
   }
}

Solution code

Android Studio project: TwoActivities

Coding challenge

Note: All coding challenges are optional and are not prerequisites for later lessons.

Challenge: Create an app with three buttons labelled: Text One, Text Two, and Text Three. When any of those buttons are clicked, launch a second activity. That second activity should contain a ScrollView that displays one of three text passages (you can include your choice of passages). Use intents to both launch the second activity and intent extras to indicate which of the three passages to display.

Summary

In this practical, you have learned that:

  • An Activity is an application component that provides a single screen focussed on a single user task.
    • Each activity has its own user interface layout file.
    • You can assign your activities a parent/child relationship to enable "upward" navigation within your app.
    • To implement an activity in your app, do the following:
  • Create an activity Java class.
  • Implement a user interface for that activity.
  • Declare that new activity in the app manifest.
  • When you create a new project for your app, or add a new activity to your app, in Android Studio (with File > New > Activity), template code for each of these tasks is provided for you.
  • Intents allow you to request an action from another component in your app, for example, to start one activity from another. Intents can be explicit or implicit.
    • With explicit intents you indicate the specific target component to receive the data.
    • With implicit intents you specify the functionality you want but not the target component.
    • Intents can include data on which to perform an action (as a URI) or additional information as intent extras.
    • Intent extras are key/value pairs in a bundle that are sent along with the intent.
  • Views can be made visible or invisible with the android:visibility attribute

The related concept documentation is in Android Developer Fundamentals: Concepts.

Learn more

results matching ""

    No results matching ""