Chapters

Hide chapters

Android Fundamentals by Tutorials

First Edition · Android 14 · Kotlin 1.9 · Android Studio Hedgehog (2023.1.1)

3. Android Fundamentals
Written by Fuad Kamal

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

A lifestyle of various activities — such as training for cardio, strength and endurance — can help keep you healthy. Although they’re all different, they each have a specific purpose or goal.

Android apps are similar, in a way. They’re built around a set of screens, each of which is known as an Activity and built around a single task. For example, you might have a settings screen where users can adjust the app’s settings or a sign-in screen where users can log in with a username and password.

In this chapter, you’ll start building an Activity focused around the main screen for Kodeco Chat — and you’ll finally get to write some Kotlin code!

Here’s an example of what the final chat application will look like:

There’s quite a lot going on in this app. For now, you’ll start with the basics.

Exploring Activities

Ensure the app folder is expanded in the Project navigator on the left. Navigate to MainActivity.kt, which you’ll find in app/kotlin+java/com.kodeco.chat/MainActivity.kt.

Open the file, and you’ll see the following contents:

package com.kodeco.chat

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.kodeco.chat.ui.theme.KodecoChatTheme

// 1
class MainActivity : ComponentActivity() {
   // 2
  override fun onCreate(savedInstanceState: Bundle?) {
    // 3    
    super.onCreate(savedInstanceState)
    // 4    
    setContent {
      KodecoChatTheme {
        // A surface container using the 'background' color from the theme
        Surface(
          modifier = Modifier.fillMaxSize(),
          color = MaterialTheme.colorScheme.background
        ) {
          Greeting("Fuad")
        }
      }
    }
  }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
  Text(
    text = "Hello $name!",
    modifier = modifier
  )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
  KodecoChatTheme {
    Greeting("Fuad")
  }
}

MainActivity.kt is where the logic for your chat screen goes. Take a moment to explore what it does:

  1. MainActivity is declared as extending ComponentActivity. It’s your first and only Activity in this app. What ComponentActivity does isn’t important right now; all you need to know is that subclassing is required to deal with content on the screen.

  2. onCreate() is the entry point to this Activity. It starts with the keyword override, meaning you’ll have to provide a custom implementation from the base ComponentActivity class.

  3. Calling the base’s implementation of onCreate() is not only important — it’s required. You do this by calling super.onCreate(). Android must set up a few things before your implementation executes, so you notify the base class that it can do so now.

  4. This line “composes” the given composable (everything that follows it in the braces {}) into the activity. The content will become the root view of the activity. ThesetContent{} block defines the activity’s layout, where composable functions are called. Composable functions can be called only from other composable functions. Therefore, the Greeting in onCreate() is just another function, defined below that, but it’s also marked with @Composable. That makes it a Composable function.

Jetpack Compose uses a Kotlin compiler plugin to transform these composable functions into the app’s UI elements. For example, inside Greeting is a Text composable function that, in turn, is defined by the Compose UI library and displays a text label on the screen. You write Composable functions to define a view layout that gets rendered on your device screen.

You’ll learn much more about Jetpack Compose in Chapters 5, “Jetpack Compose”, and 6, “Advanced Jetpack Compose”.

These four lines are the key ingredients in creating Activities for Android. You’ll see them in every Activity you create. In the most general sense, any logic you add must come after calling setContent{}.

Note: onCreate() isn’t the only entry point available for Activities, but it’s the one you should be most familiar with. onCreate() also works in conjunction with other methods you can override that make up an Activity’s lifecycle.

This book covers some of those lifecycle methods. But if you’re curious to know more already, dive deeper at https://developer.android.com/guide/components/activities/activity-lifecycle.html.

Now, you know the basics of how Activities work. Throughout the chapter, you’ll add some properties and placeholder functions and explore their purposes.

Replace the entire contents of MainActivity.kt with the following:

package com.kodeco.chat

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      Column {
        var chatInputText by remember { mutableStateOf("Type your text here") }
        var chatOutputText by remember { mutableStateOf("Press Send to update this text")}
        Text(text = chatOutputText)

        OutlinedTextField(
          value = chatInputText,
          onValueChange = {
            chatInputText = it
          },
          label = { Text("Label") }
        )

        Button(onClick = {
          chatOutputText = chatInputText
          chatInputText = ""
        }) {
          Text(text = "Send")
        }
      }
    }
  }
}

Note: Sometimes, Android Studio won’t recognize new objects in your classes until you import the class definition. Android Studio shows this by highlighting the object in red.

To import the class definition:

• macOS: Click the object and press Option-Return.

• Windows: Click the object and press Alt-Enter.

You can also let Android Studio automatically handle imports for you when pasting code. Select Android Studio ▸ Settings ▸ Editor ▸ General ▸ Auto Import. In the Kotlin section, select the Add unambiguous imports on the fly checkbox. Click Apply in the bottom right.

Going through the code:

  1. Column places a column in the view. A column is a layout group that stacks all its contents, or “children”, in a vertical column. You’ll learn all about different view layout groups in Chapter 5, “Jetpack Compose”.
  2. You define two variables, chatInputText and chatOutputText, and give them default values. Note the use of by remember. Composable functions use the remember API to store an object in memory and update it during recomposition. You’ll learn more about this in Chapter 5, “Jetpack Compose”.
  3. You define a simple Text composable to display the contents of a chat message.
  4. OutlinedTextField is a styled TextField designed to accept user input from the keyboard.
  5. Finally, you define a Button that, when tapped, updates the Text area with the text you type into the TextField.

That’s it! Run your app. Enter some text into the TextField and tap the send button. You should see the text at the top update with whatever you typed:

Congratulations! You’ve created the most basic chat app, which can accept input and display it back on screen.

A Blast From the Past: Activities, Fragments & Views

In the previous section, you built a simple layout using basic Kotlin code and the Compose UI framework. Android app development used to be much more complicated than this. You might run into legacy code in your journey as an app developer, so you should be familiar with how things used to be done as well.

chatOutputTextView = findViewById(R.id.chat_output_text_view)

Managing Strings in Your App

You have gotten your first taste of writing code, have something resembling a chat app up and running and undoubtedly want to take things further.

<resources>
  <string name="app_name">Kodeco Chat</string>
</resources>
<resources>
  <string name="app_name">Kodeco Chat</string>
  <string name="chat_display_default">Messages will display here</string>
  <string name="chat_entry_default">Type your text here</string>
  <string name="send_button">Send</string>
  <string name="chat_entry_label">Enter Chat Text</string>
</resources>

var chatInputText by remember { mutableStateOf(context.getString(R.string.chat_entry_default)) }
var chatOutputText by remember { mutableStateOf(context.getString(R.string.chat_display_default)) }

Debugging

In the previous section, you learned some basic debugging steps. But until now, you’ve used the “run app” button when you’ve run the app. Many times before, you didn’t even need to run it because Android Studio would update the running app even as you made changes. If you made a mistake — as in the previous section — while typing code that prevented the app from compiling, Android Studio alerted you to it right away. When you run the app or use the automatic preview feature, you won’t see errors that happen at run time. To see those types of error messages, you need to debug the app rather than just run it. Notice to the right of the “run app” button is another button that looks like a little bug:

Resources

Besides strings, you can have other types of resource files in Android. In this chapter, you’ll use two of those: style resources and drawable resources. For a complete list of all the resource types, see the Android developer documentation at https://developer.android.com/guide/topics/resources/available-resources.

The App Manifest

Every Android app has an app manifest. It’s important because it tells an Android device everything it needs to know about your app.

Activities

Perhaps the most interesting tags are the <activity> tags. Every Activity in an app should have a corresponding tag in the manifest. This ensures your app runs Activities only from your app and none that might have come from elsewhere.

Intents

An Intent is an object used to indicate work or an action your app will perform in the future. Currently, your app has only one Activity. But if you were to add another, you would use an Intent to navigate between the two of them. Intents are incredibly flexible and can perform various tasks, such as communicating with other apps, providing data to processes or starting up another screen.

Permissions

Later in this book, you’ll find it necessary to add various permissions to your app, such as networking permissions in Chapter 7, “Advanced Architecture”. Guess where you add permissions in an Android app? Yep, that’s right — permissions also get listed in the manifest! Permissions get added with the <permission> XML tag. Permissions are integral to security and user privacy in Android. For example, if your app wants to track a user’s location, your app would need to list one of the location services permission in the manifest and properly request the permission from the user when appropriate. For much more in-depth coverage of permissions and security in Android, see Chapters 5, “Permissions”, and 6, “Security Best Practices”, of the Android App Distribution book (https://www.kodeco.com/books/android-app-distribution).

Services

Another important component declared in the manifest is services, which are defined within the <service> tag. You use services to implement things like processes that run in the background or communications APIs. For example, Kodeco Chat might want to fetch messages in the background even when it’s not the app currently running and then notify the user that it’s received new messages.

Themes

Notice the <application> tag in the manifest has the following attribute:

Key Points

Well done setting up your first Activity. It’s a skill you’ll use over and over in your Android career. To recap, you learned:

Where to Go From Here?

With a small amount of code, you created a functional chat app while learning some foundational elements of building an Android app. Although this Activity is small, activities can get complicated as you add more Views. Later in this book, you’ll learn how to separate the logic code out of your Activities. That will leave mostly only Jetpack Compose UI code in your Activities, keeping your code separated into logical components that are easier to understand, scale and debug.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now