Your First Android Application

This first chapter is full of new concepts and moving parts required to build an Android application.

The application you are going to create is called GeoQuiz. GeoQuiz tests the user’s knowledge of geography. The user presses TRUE or FALSE to answer the question on screen, and GeoQuiz provides instant feedback.

App Basics

Your GeoQuiz application will consist of an activity and a layout:

  • An activity is an instance of Activity, a class in the Android SDK. An activity is responsible for managing user interaction with a screen of information.

  • A layout defines a set of UI objects and their positions on the screen. A layout is made up of definitions written in XML.

The relationship between QuizActivity and activity_quiz.xml is diagrammed in the figure below

Creating an Android Project

The first step is to create an Android project. An Android project contains the files that make up an application. To create a new project, first open Android Studio.

Creating a new application

Specifying device support

Choosing a type of activity If your wizard looks very different, then the tools have changed more drastically. Do not panic.

The lefthand view is the project tool window. From here, you can view and manage the files associated with your project.

Laying Out the UI

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Widgets are the building blocks you use to compose a UI. A widget can show text or graphics, interact with the user, or arrange other widgets on the screen. Buttons, text input controls, and checkboxes are all types of widgets. The Android SDK includes many widgets that you can configure to get the appearance and behavior you want. Every widget is an instance of the View class or one of its subclasses (such as TextView or Button).

But these are not the widgets you are looking for. The interface for QuizActivity requires five widgets:

  • a vertical LinearLayout

  • a TextView

  • a horizontal LinearLayout

  • two Buttons

<?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:gravity="center"
    android:orientation="vertical" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="24dp"
        android:text="@string/question_text" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/true_button" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/false_button" />
    </LinearLayout>
</LinearLayout>

The view hierarchy

Widget attributes

android:layout_width and android:layout_height

The android:layout_width and android:layout_height attributes are required for almost every type of widget. They are typically set to either match_parent or wrap_content:

Attribute

Description

match_parent

view will be as big as its parent

wrap_content

view will be as big as its contents require

android:orientation

The android:orientation attribute on the two LinearLayout widgets determines whether their children will appear vertically or horizontally. The root LinearLayout is vertical; its child LinearLayout is horizontal.

android:text

The TextView and Button widgets have android:text attributes. This attribute tells the widget what text to display.

Creating string resources

Open res/values/strings.xml. The template has already added one string resource for you. Add the three new strings that your layout requires.

<resources>
    <string name="app_name">GeoQuiz</string>
    <string name="question_text">Canberra is the capital of Australia.</string>
    <string name="true_button">True</string>
    <string name="false_button">False</string>
</resources>

Previewing the layout

Your layout is now complete, and you can preview the layout in the graphical layout tool.

From Layout XML to View Objects

When you created the GeoQuiz project, a subclass of Activity named QuizActivity was created for you. The class file for QuizActivity is in the app/java directory of your project. The java directory is where the Java code for your project lives.

package com.bignerdranch.android.geoquiz;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class QuizActivity extends AppCompatActivity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_quiz);
 }
}

Wondering what AppCompatActivity is? It is a subclass of Android’s Activity class that provides compatibility support for older versions of Android. You will learn much more about AppCompatActivity in Chapter 13

The onCreate(Bundle) method is called when an instance of the activity subclass is created. When an activity is created, it needs a UI to manage. To get the activity its UI, you call the following Activity method:

public void setContentView(int layoutResID)

This method inflates a layout and puts it on screen.

Resources and resource IDs

A layout is a resource. A resource is a piece of your application that is not code – things like image files, audio files, and XML files.

To access a resource in code, you use its resource ID. The resource ID for your layout is R.layout.activity_quiz.

To generate a resource ID for a widget, you include an android:id attribute in the widget’s definition. In activity_quiz.xml, add an android:id attribute to each button.

<LinearLayout ... >
   <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:padding="24dp"
  android:text="@string/question_text" />
   <LinearLayout
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="horizontal">
  <Button
  android:id="@+id/true_button"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/true_button" />
  <Button
  android:id="@+id/false_button"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/false_button" />
   </LinearLayout>
</LinearLayout>

Wiring Up Widgets

Now that the buttons have resource IDs, you can access them in QuizActivity. The first step is to add two member variables.

public class QuizActivity extends AppCompatActivity {
  private Button mTrueButton;
  private Button mFalseButton;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_quiz);
 }
}

Getting references to widgets

In an activity, you can get a reference to an inflated widget by calling the following Activity method:

public View findViewById(int id)

This method accepts a resource ID of a widget and returns a View object.

public class QuizActivity extends AppCompatActivity {
    private Button mTrueButton;
    private Button mFalseButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_quiz);
        mTrueButton = (Button) findViewById(R.id.true_button);
        mFalseButton = (Button) findViewById(R.id.false_button);
    }
}

Setting listeners

Android applications are typically event driven. Unlike command-line programs or scripts, event driven applications start and then wait for an event, such as the user pressing a button.

Start with the TRUE button. In QuizActivity.java, add the following code to onCreate(Bundle) just after the variable assignment.

@Override
 protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
mTrueButton = (Button) findViewById(R.id.true_button);
mTrueButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Does nothing yet, but soon!
}
});
mFalseButton = (Button) findViewById(R.id.false_button);
 }
}

Set a similar listener for the FALSE button.

mTrueButton.setOnClickListener(new View.OnClickListener() {
@Override
   public void onClick(View v) {
   // Does nothing yet, but soon!
   }
 });
 mFalseButton = (Button) findViewById(R.id.false_button);
 mFalseButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    // Does nothing yet, but soon!
    }
 });
}

Making Toasts

Now to make the buttons fully armed and operational. You are going to have a press of each button trigger a pop-up message called a toast. A toast is a short message that informs the user of something but does not require any input or action.

First, return to strings.xml and add the string resources that your toasts will display.

<resources>
  <string name="app_name">GeoQuiz</string>
  <string name="question_text">Canberra is the capital of Australia.</string>
  <string name="true_button">True</string>
  <string name="false_button">False</string>
  <string name="correct_toast">Correct!</string>
  <string name="incorrect_toast">Incorrect!</string>
</resources>
mTrueButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
        Toast.makeText(QuizActivity.this,
        R.string.correct_toast,
        Toast.LENGTH_SHORT).show();
  }
});
        mFalseButton = (Button) findViewById(R.id.false_button);
        mFalseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
        Toast.makeText(QuizActivity.this,
        R.string.incorrect_toast,
        Toast.LENGTH_SHORT).show();
 }
});

Challenge: Customizing the Toast

In this challenge, you will customize the toast to show at the top instead of the bottom of the screen. To change how the toast is displayed, use the Toast class’s setGravity method.

Last updated

Was this helpful?