Search icon CANCEL
Subscription
0
Cart icon
Cart
Close icon
You have no products in your basket yet
Save more on your purchases!
Savings automatically calculated. No voucher code required
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
How to Build Android Apps with Kotlin - Second Edition
How to Build Android Apps with Kotlin - Second Edition

How to Build Android Apps with Kotlin: A practical guide to developing, testing, and publishing your first Android apps, Second Edition

By Mr. Alex Forrester , Mr. Alexandru Dumbravan , Mr. Jomar Tigcal , Mr. Eran Boudjnah
$83.99 $57.99
Book May 2023 704 pages 2nd Edition
eBook
$83.99 $57.99
Print
$103.99
Subscription
Free Trial
Renews at $15.99p/m
eBook
$83.99 $57.99
Print
$103.99
Subscription
Free Trial
Renews at $15.99p/m

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon AI Assistant (beta) to help accelerate your learning
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Table of content icon View table of contents Preview book icon Preview Book

How to Build Android Apps with Kotlin - Second Edition

Creating Your First App

This chapter is an introduction to Android, where you will set up your environment and focus on the fundamentals of Android development. By the end of this chapter, you will have gained the knowledge required to create an Android app from scratch and install it on a virtual or physical Android device.

You will be able to analyze and understand the importance of the AndroidManifest.xml file and use the Gradle build tool to configure your app and implement user interface (UI) elements from Material Design.

Android is the most widely used mobile phone operating system in the world, with over three billion active devices. This presents great opportunities to contribute and make an impact by learning Android and building apps that have a global reach. However, for a developer who is new to Android, there are many issues you must contend with in order to get started learning and becoming productive.

This book will address these issues. After learning the tooling and development environment, you will explore fundamental practices to build Android apps. We will cover a wide range of real-world development challenges faced by developers and explore various techniques to overcome them.

In this chapter, you will learn how to create a basic Android project and add features to it. You will be introduced to the comprehensive development environment of Android Studio and learn about the core areas of the software to enable you to work productively.

Android Studio provides all the tooling for application development but not the knowledge. This first chapter will guide you through using the software effectively to build an app and configure the most common areas of an Android project.

We will cover the following topics in the chapter:

  • Creating an Android project with Android Studio
  • Setting up a virtual device and running your app
  • The Android Manifest
  • Using Gradle to build, configure, and manage app dependencies
  • Android application structure

Technical requirements

The complete code for all the exercises and the activity in this chapter is available on GitHub at https://packt.link/96l1D

Creating an Android project with Android Studio

In order to be productive in terms of building Android apps, it is essential to become confident with how to use Android Studio. This is the official integrated development environment (IDE) for Android development, built on JetBrains’ IntelliJ IDEA IDE and developed by the Android Studio team at Google. You will use it throughout this course to create apps and progressively add more advanced features.

The development of Android Studio has followed the development of the IntelliJ IDEA IDE. The fundamental features of an IDE are, of course, present, enabling you to optimize your code with suggestions, shortcuts, and standard refactoring. The programming language you will use throughout this course to create Android apps is Kotlin. Previously the standard language to create Android apps was Java.

Since Google I/O 2017 (the annual Google developer conference), this has been Google’s preferred language for Android app development. What really sets Android Studio apart from other Android development environments is that Kotlin was created by JetBrains, the company that created IntelliJ IDEA, the software Android Studio is built on. Therefore, you can benefit from established and evolving first-class support for Kotlin.

Kotlin was created to address some of the shortcomings of Java in terms of verbosity, handling null types, and adding more functional programming techniques, amongst many other issues. As Kotlin has been the preferred language for Android development since 2017, taking over from Java, you will use it in this book.

Getting to grips and familiarizing yourself with Android Studio will enable you to feel confident working on and building Android apps. So, let’s get started creating your first project.

Note

The installation and setup of Android Studio are covered in the Preface. Please ensure you have completed those steps before you continue.

Exercise 1.01 – creating an Android Studio project for your app

This is the starting point for creating a project structure your app will be built upon. The template-driven approach will enable you to create a basic project in a short timeframe while setting up the building blocks you can use to develop your app.

To complete this exercise, perform the following steps:

  1. Upon opening Android Studio, you will see a window asking whether you want to create a new project or open an existing one. Select Create New Project.
  2. Now, you’ll enter a simple wizard-driven flow, which greatly simplifies the creation of your first Android project. The next screen you will see has a large number of options for the initial setup you’d like your app to have:
Figure 1.1 – Starting a project template for your app

Figure 1.1 – Starting a project template for your app

  1. Welcome to your first introduction to the Android development ecosystem. The word displayed in most of the project types is Activity. In Android, an Activity is a page or screen. The options you can choose from all create this initial screen differently.

The descriptions describe how the first screen of the app will look. These are templates to build your app with. Select Empty Activity from the template and click on Next.

The project configuration screen is as follows:

Figure 1.2 – Project configuration

Figure 1.2 – Project configuration

  1. The preceding screen configures your app. Let’s go through all the options:
    • Name: Similar to the name of your Android project, this name will appear as the default name of your app when it’s installed on a phone and visible on Google Play.
    • Package name: This uses the standard reverse domain name pattern to create a name. It will be used as an address identifier for source code and assets in your app. It is best to make this name as clear and descriptive and as closely aligned with the purpose of your app as possible. Therefore, it’s probably best to change this to use one or more sub-domains (such as com.sample.shop.myshop). As shown in Figure 1.2, the Name value of the app (in lowercase with spaces removed) is appended to the domain.
    • Save location: This is the local folder on your machine where the app will initially be stored. This can be changed in the future, so you can probably keep the default or edit it to something different (such as Users/MyUser/android/projects). The default location will vary with the operating system you are using. By default, the project will be saved into a new folder with the name of the application with spaces removed. This results in a MyApplication project folder being created. Please change this to the Exercise or Activity that you are working on, so for this project, name the folder Exercise1.01.
    • Language: Kotlin is Google’s preferred language for Android app development.
    • Minimum SDK: Depending on which version of Android Studio you download, the default might be the same as shown in Figure 1.2 or a different version. Keep this the same. Most of Android’s new features are made backward compatible, so your app will run fine on the vast majority of older devices. However, if you do want to target newer devices, you should consider raising the minimum API level. There is a Help Me Choose link to a dialog that explains the feature set that you have access to with a view to development on different versions of Android and the current percentage of devices worldwide running each Android version.
    • Use legacy android.support libraries: Leave this unchecked. You will be using AndroidX libraries, which are the replacement for the support libraries that were designed to make features on newer versions of Android backward compatible with older versions, but it provides much more than this. It also contains new Android components called Jetpack, which, as the name suggests, boosts your Android development and provide a host of rich features you will want to use in your app, thereby simplifying common operations.

Once you have filled in all these details, select Finish. Your project will be built, and you will then be presented with the following screen or similar. You can immediately see the activity that has been created (MainActivity) in one tab and the layout used for the screen in the other tab (activity_main.xml). The application structure folders are in the left panel:

Figure 1.3 – Android Studio default project

Figure 1.3 – Android Studio default project

In this exercise, you have gone through the steps to create your first Android app using Android Studio. This template-driven approach has shown you the core options you need to configure for your app.

In the next section, you will set up a virtual device and see your app run for the first time.

Setting up a virtual device and running your app

As a part of installing Android Studio, you downloaded and installed the latest Android software development kit (SDK) components. These included a base emulator, which you will configure to create a virtual device to run Android apps on. An emulator mimics the hardware and software features and configuration of a real device. The benefit is that you can make changes and quickly see them on your desktop while developing your app. Although virtual devices do not have all the features of a real device, the feedback cycle is often quicker than going through the steps of connecting a real device.

Also, although you should ensure your app runs as expected on different devices, you can standardize it by targeting a specific device by downloading a device profile, even if you don’t have a real device if this is a requirement of your project.

The screen you will have seen (or something similar) when installing Android Studio is as follows:

Figure 1.4 – SDK components

Figure 1.4 – SDK components

Let’s take a look at the SDK components that are installed and how the virtual device fits in:

  • Android Emulator: This is the base emulator, which we will configure to create virtual devices of different Android makes and models.
  • Android SDK Build-Tools: Android Studio uses the build tools to build your app. This process involves compiling, linking, and packaging your app to prepare it for installation on a device.
  • Android SDK Platform: This is the version of the Android platform that you will use to develop your app. The platform refers to the API level.
  • Android SDK Platform-Tools: These are tools you can use, ordinarily, from the command line, to interact with and debug your app.
  • Android SDK Tools: In contrast to the platform tools, these are tools that you use predominantly from within Android Studio in order to accomplish certain tasks, such as the virtual device for running apps and the SDK manager to download and install platforms and other components of the SDK.
  • Intel x86 Emulator Accelerator (HAXM installer): If your OS provides it, this is a feature at the hardware level of your computer you will be prompted to enable, which allows your emulator to run more quickly.
  • SDK Patch Applier v4: As newer versions of Android Studio become available, this enables patches to be applied to update the version you are running.

With this knowledge, let’s start with the next exercise of this chapter.

Exercise 1.02 – setting up a virtual device and running your app on it

We set up an Android Studio project to create our app in Exercise 1.01, Creating an Android Studio project for your app, and we are now going to run it on a virtual device. You can also run your app on a real device, but you will use a virtual device in this exercise. This process is a continuous cycle while working on your app. Once you have implemented a feature, you can verify its look and behavior as you require.

For this exercise, you will create a single virtual device, but you should ensure you run your app on multiple devices to verify that its look and behavior are consistent. Perform the following steps:

  1. In the toolbar in Android Studio, you will see two drop-down boxes next to each other with app and No devices pre-selected:
Figure 1.5 – The Android Studio toolbar

Figure 1.5 – The Android Studio toolbar

app is the configuration of the app that we will run. As we haven’t set up a virtual device yet, it says No devices.

  1. In order to create a virtual device, click on Device Manager, as shown in Figure 1.5, to open the virtual devices window/screen. The option to do this can also be accessed from the Tools menu:
Figure 1.6 – Device Manager in the Tools menu

Figure 1.6 – Device Manager in the Tools menu

  1. Click the button or toolbar option to open the Device Manager window and click the Create device button, as shown in Figure 1.7:
Figure 1.7 – The Device Manager window

Figure 1.7 – The Device Manager window

You will then be presented with a screen, as shown in Figure 1.8:

Figure 1.8 – Device definition creation

Figure 1.8 – Device definition creation

  1. We are going to choose the Pixel 6 device. The real (non-virtual device) Pixel range of devices is developed by Google and has access to the most up-to-date versions of the Android platform. Once selected, click the Next button:
Figure 1.9 – System Image

Figure 1.9 – System Image

The Tirimasu name displayed here is the initial code/release name for Android 13. Select the latest system image available. The Target column might also show (Google Play) or (Google APIs) in the name. Google APIs mean that the system image comes pre-installed with Google Play Services.

This is a rich feature set of Google APIs and Google apps that your app can use and interact with. On first running the app, you will see apps such as Maps and Chrome instead of a plain emulator image. A Google Play system image means that, in addition to the Google APIs, the Google Play app will also be installed.

  1. You should develop your app with the latest version of the Android platform to benefit from the latest features. On first creating a virtual device, you will have to download the system image. If a Download link is displayed next to Release Name, click on it, and wait for the download to complete. Select the Next button to see the virtual device you have set up:
Figure 1.10 – Virtual device configuration

Figure 1.10 – Virtual device configuration

  1. Click Finish, and your virtual device will be created. You will then see your device highlighted:
Figure 1.11 – Virtual devices listed

Figure 1.11 – Virtual devices listed

  1. Press the play arrow button under the Actions column to run the virtual device:
Figure 1.12 – Virtual device launched

Figure 1.12 – Virtual device launched

You will then see the virtual device running within Android Studio in the Emulator tool window. Now that you’ve created the virtual device and it’s running, you can go back into Android Studio to run your app.

  1. The virtual device you have set up and started will be selected. Press the green triangle/play button to launch your app:
Figure 1.13 – App launch configuration

Figure 1.13 – App launch configuration

This will load the app into the emulator as shown in Figure 1.14.

Figure 1.14 – The app running on a virtual device

Figure 1.14 – The app running on a virtual device

In this exercise, you have gone through the steps to create a virtual device and run the app you created on it. The Android Virtual Device Manager, which you have used to do this, enables you to create the device (or range of devices) you would like to target your app for. Running your app on the virtual device allows a quick feedback cycle to verify how a new feature development behaves and that it displays the way you expect it to.

Next, you will explore the AndroidManifest.xml file of your project, which contains the information and configuration of your app.

The Android manifest

The app you have just created, although simple, encompasses the core building blocks that you will use in all of the projects you create. The app is driven from the AndroidManifest.xml file, a manifest file that details the contents of your app. It is located at app | manifests | AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=
    "http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_
              rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <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>
    </application>
</manifest>

A typical manifest file, in general terms, is a top-level file that describes the enclosed files or other data and associated metadata that forms a group or unit. The Android manifest applies this concept to your Android app as an XML file.

Every Android app has an application class that allows you to configure the app. After the <application> element opens, you define your app’s components. As we have just created our app, it only contains the first screen shown in the following code:

<activity android:name=".MainActivity">

The next child XML node specified is as follows:

<intent-filter>

Android uses intents as a mechanism for interacting with apps and system components. Intents get sent, and the intent filter registers your app’s capability to react to these intents. <android.intent.action.MAIN> is the main entry point into your app, which, as it appears in the enclosing XML of .MainActivity, specifies that this screen will be started when the app is launched. Android.intent.category.LAUNCHER states that your app will appear in the launcher of your user’s device.

As you have created your app from a template, it has a basic manifest that will launch the app and display an initial screen at startup through an Activity component. Depending on which other features you want to add to your app, you may need to add permissions in the Android manifest file.

Permissions are grouped into three different categories: normal, signature, and dangerous:

  • Normal: These permissions include accessing the network state, Wi-Fi, the internet, and Bluetooth. These are usually permitted without asking for the user’s consent at runtime.
  • Signature: These permissions are shared by the same group of apps that must be signed with the same certificate. This means these apps can share data freely, but other apps can’t get access.
  • Dangerous: These permissions are centered around the user and their privacy, such as sending SMS, access to accounts and location, and reading and writing to the filesystem and contacts.

These permissions have to be listed in the manifest, and in the case of dangerous permissions, from Android Marshmallow API 23 (Android 6 Marshmallow) onward, you must also ask the user to grant the permissions at runtime.

In the next exercise, we will configure the Android Manifest. Detailed documentation on this file can be found at https://developer.android.com/guide/topics/manifest/manifest-intro.

Exercise 1.03 – configuring the Android manifest internet permission

The key permission that most apps require is access to the internet. This is not added by default. In this exercise, we will fix that and, in the process, load a WebView, which enables the app to show web pages. This use case is very common in Android app development as most commercial apps will display a privacy policy, terms and conditions, and so on. As these documents are likely common to all platforms, the usual way to display them is to load a web page. To do this, perform the following steps:

  1. Create a new Android Studio project as you did in Exercise 1.01, Creating an Android Studio project for your app.
  2. Switch tabs to the MainActivity class. From the main project window, it’s located at app | java | com | example | myapplication.

You can change what the project window displays by opening up the Tool window by selecting View | Tool Windows | Project – this will select Project view. The drop-down options on the top of the Project window allow you to change the way you view your project, with the most commonly used displays being Project and Android:

Figure 1.15 – The Tool Windows drop-down menu

Figure 1.15 – The Tool Windows drop-down menu

On opening the MainActivity class, you’ll see that it has the following content or similar:

package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

You’ll examine the contents of this file in more detail in the next section of this chapter, but for now, you just need to be aware that the setContentView(R.layout.activity_main) statement sets the layout of the UI you saw when you first ran the app in the virtual device.

  1. Use the following code to change this to the following:
    package com.example.myapplication
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.webkit.WebView
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?){
            super.onCreate(savedInstanceState)
            val webView = WebView(this)
            webView.settings.javaScriptEnabled = true
            setContentView(webView)
            webView.loadUrl("https://www.google.com")
        }
    }

So, you are replacing the layout file with WebView. The val keyword is a read-only property reference, which can’t be changed once it has been set. JavaScript needs to be enabled in WebView to execute JavaScript.

Note

We are not setting the type, but Kotlin has type inference, so it will infer the type if possible. So, specifying the type explicitly with val webView: WebView = WebView(this) is not necessary. Depending on which programming languages you have used in the past, the order of defining the parameter name and type may or may not be familiar. Kotlin follows Pascal notation, that is, name followed by type.

  1. Now, run the app up, and the text will appear as shown in the screenshot here:
Figure 1.16 – No internet permission error message

Figure 1.16 – No internet permission error message

  1. This error occurs because there is no INTERNET permission added to your AndroidManifest.xml file. (If you get the net::ERR_CLEARTEXT_NOT_PERMITTED error, this is because the URL you are loading into WebView is not HTTPS, and non-HTTPS traffic is disabled from API level 28, Android 9.0 Pie and above).
  2. Let’s fix that by adding the INTERNET permission to the manifest. Open up the Android manifest and add the following above the <application> tag:
    <uses-permission android:name="android.permission.INTERNET" />

You can find the full Android manifest file with the permission added here: https://packt.link/smzpl

Uninstall the app from the virtual device before running up the app again. You need to do this, as app permissions can sometimes get cached.

Do this by long-pressing on the app icon and selecting the App Info option that appears and then pressing the Bin icon with the Uninstall text below it. Alternatively, long press the app icon and then drag it to the Bin icon with the Uninstall text beside it in the top-right corner of the screen.

  1. Install the app again and see the web page appear in WebView:
Figure 1.17 – App displaying WebView

Figure 1.17 – App displaying WebView

In this example, you learned how to add a permission to the manifest. The Android Manifest can be thought of as a table of contents of your app. It lists all the components and permissions your app uses. As you have seen from starting the app from the launcher, it also provides the entry points into your app.

In the next section, you will explore the Android build system, which uses the Gradle build tool to get your app up and running.

Using Gradle to build, configure, and manage app dependencies

In the course of creating this project, you have principally used the Android platform SDK. The necessary Android libraries were downloaded when you installed Android Studio. However, these are not the only libraries that are used to create your app. To configure and build your Android project or app, a build tool called Gradle is used.

Gradle is a multi-purpose build tool that Android Studio uses to build your app. By default, Android Studio uses Groovy, a dynamically typed Java virtual machine (JVM) language, to configure the build process and allows easy dependency management so you can add libraries to your project and specify the versions.

Android Studio can also be configured to use Kotlin to configure builds, but as the default language is Groovy, you will be using this. The files that this build and configuration information is stored in are named build.gradle.

When you first create your app, there are two build.gradle files, one at the root/top level of the project and one specific to your app in the app module folder.

The project-level build.gradle file

Let’s now have a look at the project-level build.gradle file. This is where you set up all the root project settings, which can be applied to sub-modules/projects:

plugins {
    id 'com.android.application' version '7.4.2' apply
    false
    id 'com.android.library' version '7.4.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0'
    apply false
}

Gradle works on a plugin system, so you can write your own plugin that does a task or series of tasks and plug it into your build pipeline. The three plugins listed previously do the following:

  • com.android.application: This adds support to create an Android application
  • com.android.library: This enables sub-projects/modules to be Android libraries
  • org.jetbrains.kotlin.android: This provides integration and language support for Kotlin in the project

The apply false statement enables these plugins only to sub-projects/modules, and not the project’s root level. The version '7.3.1' specifies the plugin version, which is applied to all sub-projects/modules.

The app-level build.gradle file

The build.gradle app is specific to your project configuration:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}
android {
    namespace 'com.example.myapplication'
    compileSdk 33
    defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 24
        targetSdk 33
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner
            "androidx.test.runner.AndroidJUnitRunner"}
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-
               android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}
dependencies {…}

The plugins for Android and Kotlin, detailed in the root build.gradle file, are applied to your project here by ID in the plugins lines.

The android block, provided by the com.android.application plugin, is where you configure your Android-specific configuration settings:

  • namespace: This is set from the package name you specified when creating the project. It will be used for generating build and resource identifiers.
  • compileSdk: This is used to define the API level the app has been compiled with, and the app can use the features of this API and lower.
  • defaultConfig: This is the base configuration of your app.
  • applicationId: This is set to your app’s package and is the app identifier that is used on Google Play to uniquely identify your app. It can be changed to be different from the package name if required.
  • minSdk: This is the minimum API level your app supports. This will filter out your app from being displayed in Google Play for devices that are lower than this.
  • targetSdk: This is the API level you are targeting. This is the API level your built app is intended to work and has been tested with.
  • versionCode: This specifies the version code of your app. Every time an update needs to be made to the app, the version code needs to be increased by one or more.
  • versionName: A user-friendly version name that usually follows semantic versioning of X.Y.Z, where X is the major version, Y is the minor version, and Z is the patch version, for example, 1.0.3.
  • testInstrumentationRunner: This is the test runner to use for your UI tests.
  • buildTypes: Under buildTypes, a release is added that configures your app to create a release build. The minifyEnabled value, if set to true, will shrink your app size by removing any unused code, as well as obfuscating your app. This obfuscation step changes the name of the source code references to values such as a.b.c(). This makes your code less prone to reverse engineering and further reduces the size of the built app.
  • compileOptions: This is the language level of the Java source code (sourceCompatibility) and byte code (targetCompatibility).
  • kotlinOptions: This is the jvm library the kotlin gradle plugin should use.

The dependencies block specifies the libraries your app uses on top of the Android platform SDK, as shown here (with added comments):

    dependencies {
    // Kotlin extensions, jetpack component with Android
       Kotlin language features
    implementation 'androidx.core:core-ktx:1.7.0'
    // Provides backwards compatible support libraries and
       jetpack components
    implementation 'androidx.appcompat:appcompat:1.6.1'
    // Material design components to theme and style your
       app
    implementation
        'com.google.android.material:material:1.8.0'
    // The ConstraintLayout ViewGroup updated separately
       from main Android sources
    implementation
        'androidx.constraintlayout:constraintlayout:2.1.4'
    // Standard Test library for unit tests
    testImplementation 'junit:junit:4.13.2'
    // UI Test runner
    androidTestImplementation
        'androidx.test.ext:junit:1.1.5'
    // Library for creating Android UI tests
    androidTestImplementation
        'androidx.test.espresso:espresso-core:3.5.1'
    }

The dependencies follow the Maven Project Object Model (POM) convention of groupId, artifactId, and versionId separated by :. So, as an example, the compatible support library specified earlier is shown as:

'androidx.appcompat:appcompat:1.6.1'

The groupId is android.appcompat, artifactId is appcompat, and versionId is 1.5.1. The build system locates and downloads these dependencies to build the app from the repositories block detailed in the settings.gradle file explained in the following section.

Note

The dependency versions specified in the previous code section and in the following sections of this and other chapters are subject to change and are updated over time, so they are likely to be higher when you create these projects.

The implementation notation for adding these libraries means that their internal dependencies will not be exposed to your app, making compilation faster.

Here, the androidx components are added as dependencies rather than in the Android platform source. This is so that they can be updated independently from Android versions. androidx contains the suite of Android Jetpack libraries and the repackaged support library.

The next Gradle file to examine is settings.gradle, which initially looks like this:

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "My Application"
include ':app'

On first creating a project with Android Studio, there will only be one module, app, but when you add more features, you can add new modules that are dedicated to containing the source of a feature rather than packaging it in the main app module.

These are called feature modules, and you can supplement them with other types of modules, such as shared modules, which are used by all other modules, like a networking module. This file also contains the repositories of the plugins and dependencies to download from in separate blocks for plugins and dependencies.

Setting the value of RepositoriesMode.FAIL_ON_PROJECT_REPOS ensures all dependencies repositories are defined here; otherwise, a build error will be triggered.

Exercise 1.04 – exploring how Material Design is used to theme an app

In this exercise, you will learn about Google’s new design language, Material Design, and use it to load a Material Design-themed app. Material Design is a design language created by Google that adds enriched UI elements based on real-world effects such as lighting, depth, shadows, and animations. Perform the following steps to complete the exercise:

  1. Create a new Android Studio project as you did in Exercise 1.01, Creating an Android Studio project for your app.
  2. First, look at the dependencies block and find the Material Design dependency:
    implementation 
    'com.google.android.material:material:1.8.0'
  3. Next, open the themes.xml file located at app | src | main | res | values | themes.xml: There is also a themes.xml file in the values-night folder used for a dark mode, which we will explore later:
    <resources xmlns:tools="http://schemas.android.com/tools">
        <!-- Base application theme. -->
        <style name="Theme.MyApplication" parent="Theme.
            MaterialComponents.DayNight.DarkActionBar">
            <!-- Primary brand color. -->
            <item name="colorPrimary">@color/purple_500
                </item>
            <item name="colorPrimaryVariant">@color/
                purple_700</item>
            <item name="colorOnPrimary">@color/white</item>
            <!-- Secondary brand color. -->
            <item name="colorSecondary">@color/teal_200
                </item>
            <item name="colorSecondaryVariant">@color/
                teal_700</item>
            <item name="colorOnSecondary">@color/black</item>
            <!-- Status bar color. -->
            <item name="android:statusBarColor">?attr/
                colorPrimaryVariant</item>
            <!-- Customize your theme here. -->
        </style>
    </resources>

Notice that the parent of Theme.MyApplication is Theme.MaterialComponents.DayNight.DarkActionBar.

The Material Design dependency added in the dependencies block is being used here to apply the theme of the app. One of the key differences that Material Design Components (MDC) offer over the AppCompat themes that preceded them is the ability to provide variations to the primary and secondary colors of your app.

For example, colorPrimaryVariant enables you to add a tint to the primary color, which can be either lighter or darker than the colorPrimary color. In addition, you can style view element colors in the foreground of your app with colorOnPrimary.

Together these bring cohesive branding to theme your app. To see this in effect, make the following changes to invert the primary and secondary colors:

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.MyApplication" parent="Theme.
        MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/teal_200</item>
        <item name="colorPrimaryVariant">@color/
            teal_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/purple_200
            </item>
        <item name="colorSecondaryVariant">@color/
            purple_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor">?attr/
            colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
</resources>
  1. Run the app now, and you will see the app themed differently. The action bar and status bar have changed background color in contrast to the default Material themed app, as shown in Figure 1.18:
Figure 1.18 – App with primary and secondary colors inverted

Figure 1.18 – App with primary and secondary colors inverted

In this exercise, you’ve learned how Material Design can be used to theme an app. As you are currently only displaying TextView on the screen, it is not clear what benefits material design provides, but this will change when you start using Material UI design widgets more.

Now that you’ve learned how the project is built and configured, in the next section, you’ll explore the project structure in detail, learn how it has been created, and gain familiarity with the core areas of the development environment.

Android application structure

Now that we have covered how the Gradle build tool works, we’ll explore the rest of the project. The simplest way to do this is to examine the folder structure of the app. There is a tool window at the top left of Android Studio called Project, which allows you to browse the contents of your app.

By default, it is set to open/selected when your Android project is first created. When you select it, you will see a view similar to the screenshot in Figure 1.19. If you can’t see any window bars on the left-hand side of the screen, then go to the top toolbar and select View | Appearance | Tool Window Bars and make sure it is ticked.

There are many different options for how to browse your project, but Android will be pre-selected. This view neatly groups the app folder structure, so let’s take a look at it.

Here is an overview of these files with more detail about the most important ones. On opening it, you will see that it consists of the following folder structure:

Figure 1.19 – Overview of the files and folder structure in the app

Figure 1.19 – Overview of the files and folder structure in the app

The Kotlin file (MainActivity), which you’ve specified as running when the app starts, is as follows:

package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

The import statements include the libraries and the source of what this activity uses. The class MainActivity : AppCompatActivity() class header creates a class that extends AppCompatActivity. In Kotlin, the : character is used for both deriving from a class (also known as inheritance) and implementing an interface.

MainActivity derives from androidx.appcompat.app.AppCompatActivity, which is the backward-compatible activity designed to make your app work on older devices.

Android activities have many callback functions you can override at different points of the activity’s life. This is known as the activity lifecycle. For this activity, as you want to display a screen with a layout, you override the onCreate function as shown here:

override fun onCreate(savedInstanceState: Bundle?)

The override keyword in Kotlin specifies that you are providing a specific implementation for a function defined in the parent class. The fun keyword (as you may have guessed) stands for function. The savedInstanceState: Bundle? parameter is Android’s mechanism for restoring previously saved state. For this simple activity, you haven’t stored any state, so this value will be null. The question mark, ?, that follows the type declares that this type can be null.

The super.onCreate(savedInstanceState) line calls through to the overridden method of the base class, and finally, setContentView(R.layout.activity_main) loads the layout we want to display in the activity; otherwise, it would be displayed as a blank screen as no layout has been defined.

Let’s have a look at some other files (Figure 1.19) present in the folder structure:

  • ExampleInstrumentedTest: This is an example UI test. You can check and verify the flow and structure of your app by running tests on the UI when the app is running.
  • ExampleUnitTest: This is an example unit test. An essential part of creating an Android app is writing unit tests to verify that the source code works as expected.
  • ic_launcher_background.xml and ic_launcher_foreground.xml: These two files together make up the launcher icon of your app in vector format, which will be used by the ic_launcher.xml launcher icon file in Android API 26 (Oreo) and above.
  • activity_main.xml: This is the layout file that was created by Android Studio when we created the project. It is used by MainActivity to draw the initial screen content, which appears when the app runs:
    <?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_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

Screen displays in Android can be created using XML or Jetpack Compose, which uses a declarative API to dynamically build your UI. You will learn Jetpack Compose in Chapter 9. For XML, the documents start with an XML header followed by a top-level ViewGroup (which here is ConstraintLayout) and then one or more nested Views and ViewGroups.

The ConstraintLayout ViewGroup allows very precise positioning of views on a screen, constraining views with parent and sibling views, guidelines, and barriers. Detailed documentation on ConstraintLayout can be found at https://developer.android.com/reference/androidx/constraintlayout/widget/ConstraintLayout.

TextView, currently the only child view of ConstraintLayout, displays text on the screen through the android:text attribute. The horizontal positioning of the view is done by constraining the view to both the start and end of the parent, which centers the view horizontally as both constraints are applied.

From start to end, left-to-right languages (ltr) are read left to right, while non ltr languages are read right to left. The view is positioned vertically in the center by constraining the view to both the top and the bottom of its parent. The result of applying all four constraints centers TextView both horizontally and vertically within ConstraintLayout.

There are three XML namespaces in the ConstraintLayout tag:

  • xmlns:android: This refers to the Android-specific namespace and it is used for all attributes and values within the main Android SDK.
  • xmlns:app: This namespace is for anything not in the Android SDK. So, in this case, ConstraintLayout is not part of the main Android SDK but is added as a library.
  • xmnls:tools: This refers to a namespace used for adding metadata to the XML, which indicates where the layout is used (tools:context=".MainActivity"). It is also used to show sample text visible in previews.

The two most important attributes of an Android XML layout file are android:layout_width and android:layout_height.

These can be set to absolute values, usually of density-independent pixels (known as dip or dp) that scale pixel sizes to be roughly equivalent on different density devices. More commonly, however, these attributes have the wrap_content or match_parent values set for them. wrap_content will be as big as required to only enclose its contents. match_parent will be sized according to its parent.

There are other ViewGroups you can use to create layouts. For example, LinearLayout lays out views vertically or horizontally, FrameLayout is usually used to display a single child view, and RelativeLayout is a simpler version of ConstraintLayout, which lays out views positioned relative to the parent and sibling views.

The ic_launcher.webp files are the .webp launcher icons that have an icon for every different density of devices. This image format was created by Google and has greater compression compared to the .png images. As the minimum version of Android we are using is API 21: Android 5.0 (Jelly Bean), these .webp images are included, as support for the launcher vector format was not introduced until Android API 26 (Oreo).

The ic_launcher.xml file uses the vector files (ic_launcher_background.xml and ic_launcher_foreground.xml) to scale to different density devices in Android API 26 (Oreo) and above.

Note

To target different density devices on the Android platform, besides each one of the ic_launcher.png icons, you will see in brackets the density it targets. As devices vary widely in their pixel densities, Google created density buckets so that the correct image would be selected to be displayed depending on how many dots per inch the device has.

The different density qualifiers and their details are as follows:

  • nodpi: Density-independent resources
  • ldpi: Low-density screens of 120 dpi
  • mdpi: Medium-density screens of 160 dpi (the baseline)
  • hdpi: High-density screens of 240 dpi
  • xhdpi: Extra-high-density screens of 320 dpi
  • xxhdpi: Extra-extra-high-density screens of 480 dpi
  • xxxhdpi: Extra-extra-extra-high-density screens of 640 dpi
  • tvdpi: Resources for televisions (approx 213 dpi)

The baseline density bucket was created at 160 dots per inch for medium-density devices and is called mdpi. This represents a device where an inch of the screen is 160 dots/pixels, and the largest display bucket is xxxhdpi, which has 640 dots per inch. Android determines the appropriate image to display based on the individual device.

So, the Pixel 6 emulator has a density of approximately 411dpi, so it uses resources from the extra-extra-high-density bucket (xxhdpi), which is the closest match. Android has a preference for scaling down resources to best match density buckets, so a device with 400dpi, which is halfway between the xhdpi and xxhdpi buckets, is likely to display the 480dpi asset from the xxhdpi bucket.

To create alternative bitmap drawables for different densities, you should follow the 3:4:6:8:12:16 scaling ratio between the six primary densities. For example, if you have a bitmap drawable that’s 48x48 pixels for medium-density screens, all the different sizes should be as follows:

  • 36x36 (0.75x) for low density (ldpi)
  • 48x48 (1.0x baseline) for medium density (mdpi)
  • 72x72 (1.5x) for high density (hdpi)
  • 96x96 (2.0x) for extra-high density (xhdpi)
  • 144x144 (3.0x) for extra-extra-high density (xxhdpi)
  • 192x192 (4.0x) for extra-extra-extra-high density (xxxhdpi)

For a comparison of these physical launcher icons per density bucket, refer to the following table:

Figure 1.20 – Comparison of principal density bucket launcher image sizes

Figure 1.20 – Comparison of principal density bucket launcher image sizes

Note

Launcher icons are made slightly larger than normal images within your app as they will be used by the device’s launcher. As some launchers can scale up the image, this ensures there is no pixelation and blurring of the image.

Now you are going to look at some of the resources the app uses. These are referenced in XML files and keep the display and formatting of your app consistent.

In the colors.xml file, you define the colors you want to use in your app in hexadecimal format:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
</resources>

The format is based on the ARGB color space, so the first two characters are for Alpha (transparency), the next two for Red, the next two for Green, and the last two for Blue. For Alpha, #00 is completely transparent through to #FF, which is completely opaque. For the colors, #00 means none of the color is added to make up the composite color, and #FF means all of the color is added.

If no transparency is required, you can omit the first two characters. So, to create fully blue and 50% transparent blue colors, here’s the format:

    <color name="colorBlue">#0000FF</color>
    <color name=
        "colorBlue50PercentTransparent">#770000FF</color>

The strings.xml file displays all the text displayed in the app:

<resources>
    <string name="app_name">My Application</string>
</resources>

You can use hardcoded strings in your app, but this leads to duplication and also means you cannot customize the text if you want to make the app multilingual. By adding strings as resources, you can also update the string in one place if it is used in different places in the app.

Common styles you would like to use throughout your app are added to the themes.xml file:

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.MyApplication" parent=
        "Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700
            </item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700
            </item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor"
            tools:targetApi="l">?attr/colorPrimaryVariant
                </item>
        <!-- Customize your theme here. -->
    </style></resources>

It is possible to apply style information directly to views by setting android:textStyle="bold" as an attribute on TextView. However, you would have to repeat this in multiple places for every TextView you wanted to display in bold. Furthermore, when you start to have multiple style attributes added to individual views, it adds a lot of duplication and can lead to errors when you want to make a change to all similar views and miss changing a style attribute in one view.

If you define a style, you only have to change the style, and it will update all the views that have that style applied to them. A top-level theme was applied to the application tag in the AndroidManifest.xml file when you created the project and is referred to as a theme that styles all views contained within the app.

The colors you have defined in the colors.xml file are used here. In effect, if you change one of the colors defined in the colors.xml file, it will now propagate to style the app as well.

You’ve now explored the core areas of the app. You have added the TextView views to display labels, headings, and blocks of text. In the next exercise, you will be introduced to UI elements allowing the user to interact with your app.

Exercise 1.05 – adding interactive UI elements to display a bespoke greeting to the user

The goal of this exercise is to add the capability of users to add and edit text and then submit this information to display a bespoke greeting with the entered data. You will need to add editable text views to achieve this. The EditText view is typically how this is done and can be added in an XML layout file like this:

<EditText
    android:id="@+id/full_name"
    style="@style/TextAppearance.AppCompat.Title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="@string/first_name" />

This uses an Android TextAppearance.AppCompat.Title style to display a title, as shown in Figure 1.21:

Figure 1.21 – EditText with a hint

Figure 1.21 – EditText with a hint

Although this is perfectly fine to enable the user to add/edit text, the TextInputEditText material and its wrapper TextInputLayout view give some polish to the EditText display. Here’s how EditText can be updated:

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/first_name_wrapper"
        style="@style/text_input_greeting"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/first_name_text">
        <com.google.android.material.textfield
            .TextInputEditText 
            android:id="@+id/first_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </com.google.android.material.textfield.TextInputLayout>

The output is as follows:

Figure 1.22 – The TextInputLayout/TextInputEditText material with a hint

Figure 1.22 – The TextInputLayout/TextInputEditText material with a hint

TextInputLayout allows us to create a label for the TextInputEditText view and does a nice animation when the TextInputEditText view is focused (moving to the top of the field) while still displaying the label. The label is specified with android:hint.

You will change the Hello World text in your app so a user can enter their first and last name and further display a greeting by pressing a button. To do this, perform the following steps:

  1. Create a new Android Studio project as you did in Exercise 1.01, Creating an Android Studio project for your app, called My Application.
  2. Create the labels and text you are going to use in your app by adding these entries to app | src | main | res | values | strings.xml:
    <string name="first_name_text">First name:</string>
    <string name="last_name_text">Last name:</string>
    <string name="enter_button_text">Enter</string>
    <string name="welcome_to_the_app">Welcome to the app</string>
    <string name="please_enter_a_name">Please enter a full name!</string>
  3. Next, we will update our styles to use in the layout by adding the following styles to the app | src | main | res | values | themes.xml theme:
    <style name="text_input_greeting" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
        <item name="android:layout_margin">8dp</item>
    </style>
    <style name="button_greeting">
        <item name="android:layout_margin">8dp</item>
        <item name="android:gravity">center</item>
    </style>
    <style name="greeting_display" parent="@style/TextAppearance.MaterialComponents.Body1">
        <item name="android:layout_margin">8dp</item>
        <item name="android:gravity">center</item>
        <item name="android:layout_height">40dp</item>
    </style>
    <style name="screen_layout_margin">
        <item name="android:layout_margin">12dp</item>
    </style>

Note

The parents of some of the styles refer to Material styles, so these styles will be applied directly to the views and the styles specified.

  1. Now that we have added the styles we want to apply to views in the layout and the text, we can update the layout in activity_main.xml in the app | src | main | res | layout folder:
    <?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"
    style="@style/screen_layout_margin"
    tools:context=".MainActivity">
    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/first_name_wrapper"
        style="@style/text_input_greeting"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/first_name_text"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent">
        <com.google.android.material.textfield.
            TextInputEditText android:id="@+id/first_name" 
            android:layout_width="match_parent" android:layout_
            height="wrap_content" />
    </com.google.android.material.textfield.TextInputLayout>
    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/last_name_wrapper"
        style="@style/text_input_greeting"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/last_name_text"
        app:layout_constraintTop_toBottomOf="@id/first_name_
            wrapper"
        app:layout_constraintStart_toStartOf="parent">
        <com.google.android.material.textfield.
            TextInputEditText android:id="@+id/last_name" 
            android:layout_width="match_parent" android:layout_
            height="wrap_content" />
    </com.google.android.material.textfield.TextInputLayout>
    <com.google.android.material.button.MaterialButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/button_greeting"
        android:id="@+id/enter_button"
        android:text="@string/enter_button_text"
        app:layout_constraintTop_toBottomOf="@id/last_name_
            wrapper"
        app:layout_constraintStart_toStartOf="parent"/>
    <TextView
        android:id="@+id/greeting_display"
        android:layout_width="match_parent"
        style="@style/greeting_display"
        app:layout_constraintTop_toBottomOf="@id/enter_
            button"
        app:layout_constraintStart_toStartOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
  2. Run the app and see the look and feel. You have added IDs for all the views so they can be constrained against their siblings and also provide a way in the activity to get the values of the TextInputEditText views. The style="@style.." notation applies the style from the themes.xml file.

If you select one of the TextInputEditText views, you’ll see the label animated and move to the top of the view:

Figure 1.23 – The TextInputEditText fields with label states with no focus and with focus

Figure 1.23 – The TextInputEditText fields with label states with no focus and with focus

  1. Now, we must add the interaction with the view in our activity. The layout by itself doesn’t do anything other than allow the user to enter text into the EditText fields. Clicking the button at this stage will not do anything. You will accomplish this by capturing the entered text by using the IDs of the form fields when the button is pressed and then using the text to populate a TextView message.
  2. Open MainActivity and complete the next steps to process the entered text and use this data to display a greeting and handle any form input errors.
  3. In the onCreate function, set a ClickListener on the button so we can respond to the button click and retrieve the form data by updating MainActivity to what is displayed in the following code block:
    package com.example.myapplication
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.view.Gravity
    import android.widget.Button
    import android.widget.TextView
    import android.widget.Toast
    import com.example.myapplication.R
    import com.google.android.material.textfield.TextInputEditText
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            findViewById<Button>(R.id.enter_button)?.
            setOnClickListener {
                //Get the greeting display text
                val greetingDisplay = 
                    findViewById<TextView>(R.id.greeting_
                    display)
                //Get the first name TextInputEditText value
                val firstName = 
                    findViewById<TextInputEditText>(R.
                    id.first_name)
                    ?.text.toString().trim()
                //Get the last name TextInputEditText value
                val lastName = 
                    findViewById<TextInputEditText>(R.
                    id.last_name)
                    ?.text.toString().trim()
                //Add code below this line in step 9 to Check 
                  names are not empty here:
            }
        }
    }
  4. Then, check that the trimmed names are not empty and format the name using Kotlin’s string templates:
    if (firstName.isNotEmpty() && lastName.isNotEmpty()) {
        val nameToDisplay = firstName.plus(" ")
            .plus(lastName)
        //Use Kotlin's string templates feature to display 
          the name
        greetingDisplay?.text = " ${getString(R.string.
            welcome_to_the_app)} ${nameToDisplay}!"
    }
  5. Finally, show a message if the form fields have not been filled in correctly:
    else {
        Toast.makeText(this, getString(R.string.please_
            enter_a_name), Toast.LENGTH_LONG)
            .apply {
                setGravity(Gravity.CENTER, 0, 0)
                show()
            }
    }

The Toast specified is a small text dialog that appears above the main layout for a short time to display a message to the user before disappearing.

  1. Run the app and enter text into the fields and verify that a greeting message is shown when both text fields are filled in, and a pop-up message appears with why the greeting hasn’t been set if both fields are not filled in. You should see the following display for each one of these cases:
Figure 1.24 – The app with the name filled in correctly and with an error

Figure 1.24 – The app with the name filled in correctly and with an error

The full exercise code can be viewed at https://packt.link/UxbOu.

The preceding exercise introduced you to adding interactivity to your app with the EditText fields that a user can fill in, adding a click listener to respond to button events, and performing some validation.

Accessing Views in layout files

The established way to access Views in layout files is to use findViewById with the name of the View’s ID. So the enter_button button is retrieved by the findViewById<Button>(R.id.enter_button) syntax after the layout has been set in setContentView(R.layout.activity_main) in the Activity.

You will use this technique in this course. Google has also introduced ViewBinding to replace findViewById, which creates a binding class to access Views and has the advantage of null and type safety. You can read about this at https://developer.android.com/topic/libraries/view-binding.

Further input validation

Validating user input is a key concept in processing user data, and you must have seen it in action many times when you’ve not filled in a required field in a form. This is what the previous exercise validated when it checked that the user had entered values into both the first name and last name fields.

There are other validation options that are available directly within XML view elements. Let’s say, for instance, you wanted to validate an IP address entered into a field. You know that an IP address can be four numbers separated by periods/dots where the maximum length of a number is three.

So, the maximum number of characters that can be entered into the field is 15, and only numbers and periods/dots can be entered. Two XML attributes can help us with the validation:

  • android:digits="0123456789.": This restricts the characters that can be entered into the field by listing all the permitted individual characters
  • android:maxLength="15": This restricts the user from entering more than the maximum number of characters an IP address will consist of

So, this is how you can display this in a form field:

<com.google.android.material.textfield.TextInputLayout style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.google.android.material.textfield.TextInputEditText  android:id="@+id/ip_address"
    android:digits="0123456789."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxLength="15" />
</com.google.android.material.textfield.TextInputLayout>

This validation restricts the characters that can be input and the maximum length. Additional validation would be required on the sequence of characters and whether they are periods/dots or numbers, as per the IP address format, but it is the first step to assist the user in entering the correct characters. There is also an android:inputType XML attribute, which can be used to specify permitted characters and configure the input options, android:inputType="textPassword", for example, ensures that the characters entered are hidden. android:inputType="Phone" is the input method for a phone number.

With the knowledge gained from the chapter, let’s start with the following activity.

Activity 1.01 – producing an app to create RGB colors

In this activity, we will look into a scenario that uses validation. Suppose you have been tasked with creating an app that shows how the RGB channels of red, green, and blue are added together in the RGB color space to create a color.

Each RGB channel should be added as two hexadecimal characters, where each character can be a value of 0–9 or A–F. The values will then be combined to produce a six-character hexadecimal string that is displayed as a color within the app.

This activity aims to produce a form with editable fields in which the user can add two hexadecimal values for each color. After filling in all three fields, the user should click a button that takes the three values and concatenates them to create a valid hexadecimal color string. This should then be converted to a color and displayed in the UI of the app.

The following steps will help you to complete the activity:

  1. Create a new Android Studio project as you did in Exercise 1.01, Creating an Android Studio project for your app.
  2. Add a Title constrained to the top of the layout.
  3. Add a brief description to the user on how to complete the form.
  4. Add three material TextInputLayout fields wrapping three TextInputEditText fields that appear under Title. These should be constrained so that each view is above the other (rather than to the side). Name the TextInputEditText fields Red Channel, Green Channel, and Blue Channel, respectively, and add a restriction to each field to allow entry only of two characters and add hexadecimal characters.
  5. Add a button that takes the inputs from the three color fields.
  6. Add a view that displays the produced color in the layout.
  7. Finally, display the RGB color created from the three channels in the layout when the button is pressed and all input is valid.

The final output should look like this (the color will vary depending on the inputs):

Figure 1.25 – Output when the color is displayed

Figure 1.25 – Output when the color is displayed

Note

The solution to this activity can be found at https://packt.link/By7eE.

Note

When loading all completed projects from the GitHub repository for this course into Android Studio for the first time, do not open the project using File | Open from the top menu. Always use File | New | Import Project. This ensures the app builds correctly. When opening projects after the initial import, you can use File | Open or File | Open Recent.

Summary

This chapter has covered a lot about the foundations of Android development. You started with how to create Android projects using Android Studio and then created and ran apps on a virtual device.

The chapter then progressed by exploring the AndroidManifest file, which details the contents of your app and the permission model, followed by an introduction to Gradle and the process of adding dependencies and building your app.

This was then followed by going into the details of an Android application and the files and folder structure. Layouts and views were introduced, and exercises iterated to illustrate how to construct UIs with an introduction to Google’s Material Design.

The next chapter will build on this knowledge by learning about the activity lifecycle, activity tasks, and launch modes, persisting and sharing data between screens, and how to create robust user journeys through your apps.

mdpi

hdpi

xhdpi

xxhdpi

xxxhdpi

A picture containing application

Description automatically generated

A picture containing text, sign

Description automatically generated

A picture containing text, sign

Description automatically generated

A picture containing text, sign

Description automatically generated

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Build apps with Kotlin, Google’s preferred programming language for Android development
  • Unlock solutions to development challenges with guidance from experienced Android professionals
  • Improve your apps by adding valuable features that make use of advanced functionality

Description

Looking to kick-start your app development journey with Android 13, but don’t know where to start? How to Build Android Apps with Kotlin is a comprehensive guide that will help jump-start your Android development practice. This book starts with the fundamentals of app development, enabling you to utilize Android Studio and Kotlin to get started with building Android projects. You'll learn how to create apps and run them on virtual devices through guided exercises. Progressing through the chapters, you'll delve into Android's RecyclerView to make the most of lists, images, and maps, and see how to fetch data from a web service. You'll also get to grips with testing, learning how to keep your architecture clean, understanding how to persist data, and gaining basic knowledge of the dependency injection pattern. Finally, you'll see how to publish your apps on the Google Play store. You'll work on realistic projects that are split up into bitesize exercises and activities, allowing you to challenge yourself in an enjoyable and attainable way. You'll build apps to create quizzes, read news articles, check weather reports, store recipes, retrieve movie information, and remind you where you parked your car. By the end of this book, you'll have the skills and confidence to build your own creative Android applications using Kotlin.

What you will learn

Create maintainable and scalable apps using Kotlin Understand the Android app development lifecycle Simplify app development with Google architecture components Use standard libraries for dependency injection and data parsing Apply the repository pattern to retrieve data from outside sources Build user interfaces using Jetpack Compose Explore Android asynchronous programming with Coroutines and the Flow API Publish your app on the Google Play store

Product Details

Country selected

Publication date : May 2, 2023
Length 704 pages
Edition : 2nd Edition
Language : English
ISBN-13 : 9781837634934
Category :

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon AI Assistant (beta) to help accelerate your learning
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want

Product Details


Publication date : May 2, 2023
Length 704 pages
Edition : 2nd Edition
Language : English
ISBN-13 : 9781837634934
Category :

Table of Contents

24 Chapters
Preface Chevron down icon Chevron up icon
1. Part 1: Android Foundation Chevron down icon Chevron up icon
2. Chapter 1: Creating Your First App Chevron down icon Chevron up icon
3. Chapter 2: Building User Screen Flows Chevron down icon Chevron up icon
4. Chapter 3: Developing the UI with Fragments Chevron down icon Chevron up icon
5. Chapter 4: Building App Navigation Chevron down icon Chevron up icon
6. Part 2: Displaying Network Calls Chevron down icon Chevron up icon
7. Chapter 5: Essential Libraries: Retrofit, Moshi, and Glide Chevron down icon Chevron up icon
8. Chapter 6: Adding and Interacting with RecyclerView Chevron down icon Chevron up icon
9. Chapter 7: Android Permissions and Google Maps Chevron down icon Chevron up icon
10. Chapter 8: Services, WorkManager, and Notifications Chevron down icon Chevron up icon
11. Chapter 9: Building User Interfaces Using Jetpack Compose Chevron down icon Chevron up icon
12. Part 3: Testing and Code Structure Chevron down icon Chevron up icon
13. Chapter 10: Unit Tests and Integration Tests with JUnit, Mockito, and Espresso Chevron down icon Chevron up icon
14. Chapter 11: Android Architecture Components Chevron down icon Chevron up icon
15. Chapter 12: Persisting Data Chevron down icon Chevron up icon
16. Chapter 13: Dependency Injection with Dagger, Hilt, and Koin Chevron down icon Chevron up icon
17. Part 4: Polishing and Publishing an App Chevron down icon Chevron up icon
18. Chapter 14: Coroutines and Flow Chevron down icon Chevron up icon
19. Chapter 15: Architecture Patterns Chevron down icon Chevron up icon
20. Chapter 16: Animations and Transitions with CoordinatorLayout and MotionLayout Chevron down icon Chevron up icon
21. Chapter 17: Launching Your App on Google Play Chevron down icon Chevron up icon
22. Index Chevron down icon Chevron up icon
23. Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
(0 Ratings)
5 star 0%
4 star 0%
3 star 0%
2 star 0%
1 star 0%
Top Reviews
No reviews found
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.