Advanced iOS Summer Bundle

3 brand-new books on SwiftUI, Combine and Catalyst — $99.99 for a limited time!

Beginning Android Development with Kotlin, Part Two: Using Android Studio

In this Android Studio tutorial, you’ll learn the fundamental concepts of developing with Android Studio using Kotlin by creating an app to read your fortune.

5/5 3 Ratings

Version

  • Kotlin 1.3, Android 5.1, Android Studio 3
Update note: Kevin Moore updated this tutorial for Android Studio version 3.3.1 and Kotlin. Matt Luedke wrote the original.

Android Studio is an IntelliJ IDEA-based IDE, and it’s the official IDE for Android app development.

In this Android Studio tutorial, you’ll learn how to use the tools that every Android developer uses by creating a simple fortune telling app. You’ll learn to use some of Android Studio’s key features by:

  • Navigating through different files in your project using Project Explorer.
  • Working with the AndroidManifest.xml file.
  • Learning about the Gradle build system.
  • Importing files into your project.
  • Learning about the rich layout editor with dynamic layout previews.
  • Using Logcat and the Android Monitor to debug your app.

Note: This tutorial assumes that you’ve already installed Android Studio 3.2.1 or later and have set up an emulator or a device configured for testing. If you haven’t, please refer to our previous tutorial about installing Android Studio to get up and running in no time!

Getting Started With Android Studio

You’ll start by creating a brand new Android app that you’ll use to explore Android Studio and to learn about its capabilities and interface.

For bonus points, you’ll also walk away as a bona fide fortune teller — or something to that effect. At least you’ll have a fun app to play around with!

Fire up Android Studio and, in the Welcome to Android Studio window, select Start a new Android Studio project.

In the Choose your project window, select the Basic Activity type and press Next.

In the Configure your project window, set the Name to Fortune Ball, enter a Company domain of your choosing and select a convenient location to host your app in the Save location field. Also, make sure that the language is Kotlin and the minimum API is 21. When you’re done, click Finish.

Within a short amount of time (hopefully seconds!), you’ll land on a screen that looks similar to this:

First screen

Build and run your app and you should see a similar screen on your device or emulator. Note that the emulator acts like a device, so it will need time to boot and load.

First run Emulator

Voila, that’s an app! There’s not much to it, but it’s enough to let you dive into the next section.

Project and File Structure

For this portion of the tutorial, you’ll focus on the highlighted section of the screenshot below. This window shows the project files of your app. By default, Android Studio filters the files to show Android project files.

Project Tab

After you select the file drop-down menu as illustrated in the screenshot below, you’ll see several options to filter the files. The key filters here are Project and Android.

The Project filter will show you all of the app modules. You have to have at least one app module in every project.

Other types of modules include third-party library modules or other Android app modules such as Android wear apps, Android TV, etc… Each module has its own complete set of sources, including a gradle file, resources and source files such as Kotlin files.

Project Filter

Note: If you don’t see the Project view, you can click on the Project tab on the left side panel, as indicated in the screenshot above.

The default filter is Android, which groups files by specific types. You’ll see the following folders at the very top level:

  • Manifests
  • Java
  • Res
  • Gradle Scripts

Android Filter

Note that the source folder is named java even if you’re using Kotlin. You’ll take a deeper dive into each of these folders, starting with manifests, in the next section.

Overview of AndroidManifest.xml

Every Android app has an AndroidManifest.xml in its manifests folder. This XML file lets your system know what the app’s requirements are. It must be present for the Android system to build your app.

Go to your app’s manifests folder and expand it to select AndroidManifest.xml. Double-click on the file to open it.

Android Minfest

The manifest file must have manifest and application tags in it. Each must appear only once.

In addition to the element name, each tag also defines a set of attributes. For example, some of the many attributes in the application tag are: android:icon, android:label and android:theme.

Other common elements that can appear in the manifest include:

  • Uses-permission: Requests a special permission that the app must have in order for it to operate correctly. For example, if an app must request permission from the user in order to access the Internet, you must specify the android.permission.INTERNET permission.
  • Activity: Declares an activity that implements part of the app’s visual user interface and logic. Every activity that your app uses must appear in the manifest. The system won’t see undeclared activities and, sadly, they’ll never run.
  • Service: Declares a service that you’ll use to implement long-running background operations or a rich communications API that other apps can call. An example is a network call to fetch data for your app. Unlike activities, services have no user interface.
  • Receiver: Declares a broadcast receiver that enables apps to receive intents broadcast by the system or by other apps, even when other components of the app are not running. One example of a broadcast receiver is when the battery is low and you get a system notification within your app; you can then write logic to respond.

You can find a full list of tags allowed in the manifest file here on the Android Developer site.

Configuring the Manifest

Right now, your app is an excellent example of a framework, but it’s a terrible fortune teller. You’re here because you want to learn how to play around on Android. That’s convenient, because now you’ll need to make some changes to the manifest so that you can look into the future.

Under the activity tag in MainActivity, add the attribute android:screenOrientation="portrait" to restrict the screen to portrait mode only.

If this attribute is absent, the screen will transform to landscape or portrait mode depending on the device’s orientation. After adding this attribute, your manifest file should look like the screenshot below:

Screen Orientation

When you’re done, build and run the app. Rotate your phone or emulator and notice that the screen won’t switch into landscape mode, as you’ve restricted this capability in the manifest file.

Overview of Gradle

It’s now time to shift gears to Gradle. In a nutshell, Gradle is a build system that Android Studio uses. It takes the Android project and builds or compiles it into an installable Android Package Kit, or APK, file, which you can then install on devices.

As shown below, you can find the build.gradle file under Gradle scripts in your project at two levels: Module level and project level. Most of the time, you’ll edit the module level file.

build.gradle

Open the build.gradle (Module:app) file. You’ll see the default gradle setup:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
  compileSdkVersion 28
  defaultConfig {
    applicationId "com.raywenderlich.android.fortuneball"
    minSdkVersion 21
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar'])
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
  implementation 'com.android.support:appcompat-v7:28.0.0'
  implementation 'com.android.support.constraint:constraint-layout:1.1.3'
  implementation 'com.android.support:design:28.0.0'
  testImplementation 'junit:junit:4.12'
  androidTestImplementation 'com.android.support.test:runner:1.0.2'
  androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Now, take a step-by-step look at the major components:

  • Apply plugin: ‘com.android.application’: Applies the Android plugin at the parent level and makes available the top-level build tasks required to build an Android app.
  • Apply plugin: ‘kotlin-android’ and apply plugin: ‘kotlin-android-extensions’: Applies Kotlin-related plugins that allow your app to use the Kotlin compiler and Android-specific Kotlin extensions.
  • Android{…}: Gives you configuration options such as targetSdkVersion. You should keep the target SDK for your app at the latest API level, which was 28 at the time we published this tutorial.

    Another important component is minSDKVersion, which defines the minimum SDK version a device should have installed in order to run your app.

    For example, if your device’s SDK version is 20, then this app won’t be able to run on your device, since the minimum supported version is 21.

  • Dependencies{…}: Important dependencies like implementation 'com.android.support:appcompat-v7:VERSION' and implementation 'com.android.support:design:VERSION' provide support and compatibility of new features from the latest API to the older APIs.
  • Implementation”org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version”: Allows your code to use the Kotlin standard library.

Installing Third-Party Libraries

In addition to Android compatibility libraries, you can also add other third party libraries in the dependencies{...} component.

For this tutorial, you’ll add an animation library that will let you add cool effects to user interface elements in your app.

To put these into place, find dependencies and add the following two lines at the bottom:

  implementation 'com.daimajia.easing:library:2.0@aar'
  implementation 'com.daimajia.androidanimations:library:2.2@aar'

Here, you add two new third-party dependencies that will help you make Fortune Ball shine. Android Studio will automatically download and integrate these libraries.

In fact, once you add these dependencies, Android Studio will realize that it needs to download them and will tell you to do so. Look for a bar across the top of the build.gradle file as shown the next screenshot. Click Sync Now to integrate these dependencies in your app.

sync now

Syncing takes a few seconds. You can monitor the Gradle file update in the Messages tab in the bottom panel. Look for a success message in that panel, as shown in the screenshot below.

Messages

All right, that’s all the configuration you need to do to Gradle for now. You’re now set to add fancy animations to your app, which you’ll do a little later.

Importing Files

An important part of making an Android app is integrating resources such as images, custom fonts, sounds, videos and so on. You must import these resources into Android Studio and place them in appropriate folders. This allows the Android operating system to pick the correct resource for your app.

For Fortune Ball, you’ll import image assets and place them in drawable folders. Drawable folders can hold images or custom XML drawables. For example, you can draw shapes via XML code then use them in your app’s layouts.

Adding Image Files to Your App

To get started, download the image assets here, then unzip the contents and save them where you can access them easily.

There are two ways to import the files:

  • Copy and paste the files from your file system. You won’t use that method in this tutorial.
  • Use Android Studio to import the files.

Back in the project in Android Studio, switch the view from Android to Project. Next, open the res folder under app ▸ src ▸ main.

Now you’ll want to right-click on the res folder and select New ▸ Android resource directory.

New resource directory

You’ll get a window titled New Resource Directory. From the Resource type drop-down, select the drawable option. In the Available qualifiers list, select Density and click the button highlighted in the screenshot below:

Density qualifier

In the subsequent window, select XX-High Density from the Density drop-down, then click OK.

xx-hdpi

Repeat the same process and create drawable-xhdpi, drawable-hdpi and drawable-mdpi folders by going to the Density drop-down and selecting X-High Density, High Density and Medium Density, respectively.

Setting up Images for Different Screen Resolutions

Each drawable folder that has a density qualifier, such as xxhdpi, xhdpi and hdpi, houses images corresponding to that particular density or resolution. For example, the folder drawable-xhdpi contains images that are extra-high density, meaning an Android device with an extra-high resolution screen will pick images from this folder.

This allows your app to look great on all Android devices, regardless of the screen quality. To learn more about screen densities, check out the Android documentation.

After creating all the drawable folders, go back to the unzipped contents in your file manager, copy the image file img_crystral.png from each folder using Cmd + C on Mac or Ctrl+C on PC and paste it into the corresponding folder in Android Studio using Cmd + V, Ctrl+V on PC.

Image file copy

After you paste the files, you’ll see the Copy window. Select OK to continue.

Copy

You’ve just put the ball in Fortune Ball, and learned how to import files along the way. Looks like you just checked another feature off your to-learn list!

XML View With Dynamic Layout Previews

An incredibly important part of building an Android app is creating a layout for the app’s users to interact with.

In Android Studio, you do this in the layout editor. Start by opening content_main.xml from res/layout. You’ll initially land on the Design tab of the layout editor. In this tab, you can drag user interface elements like buttons, text fields etc. in the editor.

Design editor

On the right-hand side of the Design tab is the Text tab. Switching to this view allows you to directly edit the XML that makes up the layout.

Text editor

You’ll be able to preview the layout in either tab of the device as you build. Choose the Text tab to start building the layout for Fortune Ball.

Defining Values for Your Layout

Before you start building the view, you’ll need to define some values. Open strings.xml under res/values and add the following:

<string name="fortune_description">Suggest the question, which you can answer “yes” or “no”, then click on the magic ball.</string>

Strings.xml contains all the user-facing strings that appear in your app. Splitting the strings into their own file makes internationalization a breeze, as you just provide a strings file for each language you wish to support. Even if you don’t want to translate your app right away, it’s considered a best practice to use a strings file.

Next, open dimens.xml under res/values and add the following:

<dimen name="description_text_size">15sp</dimen>
<dimen name="fortune_text_size">20sp</dimen>

Dimens.xml contains all the dimension’s values, such as margin spacing for your layouts, your text sizes and so on. Again, it’s a good practice to keep the dimensions in this file so that you can re-use them in constructing layouts.

Creating Your Layout

Now, head back to content_main.xml and replace the entire contents of the file with the code below:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main"
    tools:context=".MainActivity">

  <TextView
      android:id="@+id/descriptionText"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:gravity="center"
      android:layout_marginTop="8dp"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      android:text="@string/fortune_description"
      android:textSize="@dimen/description_text_size"/>

  <ImageView
      android:id="@+id/fortunateImage"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:layout_constraintTop_toBottomOf="@+id/descriptionText"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      android:layout_marginTop="10dp"
      android:src="@drawable/img_crystal"/>

  <TextView
      android:id="@+id/fortuneText"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="20dp"
      android:gravity="center"
      app:layout_constraintTop_toBottomOf="@+id/fortunateImage"
      android:textColor="@android:color/holo_red_dark"
      android:textSize="@dimen/fortune_text_size"
      android:textStyle="bold"/>

  <Button
      android:id="@+id/fortuneButton"
      android:layout_width="match_parent"
      android:layout_height="50dp"
      android:layout_below="@id/fortuneText"
      android:layout_centerHorizontal="true"
      app:layout_constraintTop_toBottomOf="@+id/fortuneText"
      android:layout_marginTop="10dp"
      android:text="What's my fortune?"/>
</android.support.constraint.ConstraintLayout>

This large chunk of XML creates Fortune Ball’s layout. At the top level, you’ve added a ConstraintLayout, which will lay out the objects inside of it. It stretches to match the size of its parent — i.e., the full activity.

Within the layout, you’ve added two pieces of text, an image and a button. These will appear within the container in the order in which you added them. Strings.xml reads the content from the text views and the drawable you added reads the content for the image.

As you’re updating content_main.xml, notice how the Preview window updates the UI:

Note: If you can’t see the preview window, click on the Preview button on the right-hand side panel of the layout editor while you’re still in the Text tab.

Finally, build and run your app.

Running app

Congrats! You’ve designed your app’s layout. However, it’s only a pretty picture at this point — clicking on that button doesn’t do anything. Are you ready to play around with activities?

Connecting Views With Activities

Use the Kotlin files located in app ▸ src ▸ main ▸ java to implement your app’s logic.

Open MainActivity.kt

Inside of MainActivity.kt add the following at the top of MainActivity:

private var fortuneList = arrayOf(
  "Don’t count on it",
  "Ask again later",
  "You can rely on it",
  "Without a doubt",
  "Outlook is not so good",
  "It's decidedly so",
  "Signs point to yes",
  "Yes, definitely",
  "Yes",
  "My sources say NO"
)

private lateinit var fortuneText: TextView
private lateinit var generateFortuneButton: Button
private lateinit var fortuneBallImage: ImageView

Make sure you import the different Android widgets.

In this small chunk of code, you’ve declared four member variables for the activity. The first is an array of strings that represents the possible fortunes and the remaining three represent the UI elements you created in the layout.

Next, replace the content of onCreate() with the following:

// 1:
super.onCreate(savedInstanceState)
// 2:
setContentView(R.layout.activity_main)
val toolbar = findViewById<View>(R.id.toolbar) as Toolbar
setSupportActionBar(toolbar)
// 3:
fortuneText = findViewById<View>(R.id.fortuneText) as TextView
fortuneBallImage = findViewById<View>(R.id.fortunateImage) as ImageView
generateFortuneButton = findViewById<View>(R.id.fortuneButton) as Button

// 4:
generateFortuneButton.setOnClickListener {
  // 5:
  val index = Random().nextInt(fortuneList.size)
  fortuneText.setText(fortuneList[index])
  // 6:
  YoYo.with(Techniques.Swing)
      .duration(500)
      .playOn(fortuneBallImage)
}

Taking the numbered sections one by one:

  1. Call the superclass implementation to ensure the activity is ready to go.
  2. Specify that the the layout which you created before will provide the layout for this activity and prepare the toolbar.
  3. Populate the values of the three member variables you created before for the views in the layout using findViewById. The id value is the same as the one you provided in the XML layout.

    Note: Since you are using Kotlin Android Extensions, you don’t need findViewById calls; see more here.

  4. Add OnClickListener to the button. This is a simple class that encapsulates the functionality you’d like to perform when a user presses the button.
  5. Find a random fortune from the fortuneList array and update the fortune text to display it.
  6. Use the third-party animation library you added as a dependency to the gradle file to add a fun animation to the crystal ball image.

OK, that wasn’t too bad right? Build and run your app, then tap the button to test out your fortune-telling powers.

Running app

Tidying Up

You’re almost done. But before you start planning your release party, you have some clean-up to do, like getting rid of that floating button. Head to res ▸ layout and open activity_main.xml.

This layout file contains a reference to content_main.xml, which you previously edited. It wraps the content with the default toolbar and the floating action button. However, Fortune Ball doesn’t need a floating action button, so remove the following code block from this XML file:

<android.support.design.widget.FloatingActionButton
  android:id="@+id/fab"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="bottom|end"
  android:layout_margin="@dimen/fab_margin"
  app:srcCompat="@android:drawable/ic_dialog_email" />

Now, build and run the app. You won’t see that floating button on the bottom right-hand corner anymore:

Remove FAB button

Ask a question, tap on What’s my fortune? and let your future unfold before your eyes!

Logcat

Android Studio provides a bunch of tools to help you look under the hood of your app. You can access them from the View ▸ Tool Windows menu or by clicking the tabs at the bottom of Android Studio:

Tool tabs

Let’s walk through one of them. Don’t worry, you don’t have to memorize all this and there won’t be a quiz. :]

Click the Logcat tab:

Logcat tab

At the top, you specify the device or emulator that you want to monitor, and the “process” you are most interested in. You should select your app’s package name if it’s not already selected.

The Logcat tab has camera and play buttons to enable taking screenshots or screen video recordings.

Logcat gives you a detailed view into your device’s system messages with the ability to drill down into a specific app, or even to use the search bar to filter out messages unless they contain specific text.

Make sure you’ve selected Show only selected application in the top right, as shown in the screenshot above. Now, you’ll only see messages from your app, including those you write yourself.

Oh, what? You haven’t added any messages for yourself?

Adding Messages

Head to MainActivity.kt and add the following line at the end of onCreate() in MainActivity:

Log.v("FORTUNE APP TAG","onCreateCalled")

Make sure you choose Import for the Log class.

Log.v calls for two parameters: A tag and a message. In this case, you’ve defined the tag as “FORTUNE APP TAG” and the message as “onCreateCalled”.

To try it out, build and run the app so you can see this log message in the Logcat panel.

Logcat log statement

To filter the LogCat contents to show only your message, type onCreateCalled into the search box above the console, like this:

Filtered logcat

When you’re done, remove your search text to see all the log messages again.

Finding Out Why Your App Crashes

Another of Logcat’s useful utilities is the ability to see stacktrace or error messages from app crashes and exceptions. To try it out, add a bug to your perfectly working app to see how that works.

Go to MainActivity.kt and comment out the following line in onCreate():

//fortuneText = findViewById<View>(R.id.fortuneText) as TextView

Build and run the app. Once it launches, click the What’s My Fortune? button on the screen. Oh no! It crashed.

Sad face

How would you go about fixing this if you hadn’t put the bug in on purpose? Logcat to the rescue!

Head back to the Logcat panel — it’ll look something like this:

That sure is a lot of red text, and it’s exactly where to go to sniff around for clues. You’re looking for an exception somewhere. In this case, it’s line 45 in the MainActivity.kt file. LogCat has even helpfully turned that link into a blue hyperlink, and if you click it, it will take you right to the problematic line!

By commenting out fortuneText = findViewById(R.id.fortuneText) as TextView, you created a variable but didn’t assign it a value — hence, the uninitialized property access exception.

Go ahead and uncomment that code then build and run the app. This time there’s no crash!

Logcat is a powerful tool that lets you debug your app’s errors and exceptions.

Where to Go From Here?

You can download the final project using the Download Materials button at the top or bottom of this page.

Practice makes perfect! You’ve learned your way around Android Studio and can now create a project, play around with Gradle, import assets, set up layouts and do some testing.

There’s a lot of cool stuff to learn about Android, and I suggest you start with these next steps:

  • Get familiar with Logcat and its filtering mechanism. Filter by different criteria.
  • If you want to learn more about Android Studio 3, read our What’s New in Android Studio 3 tutorial for more details.
  • This Beginning Android Development tutorial has touched on some of the tools used to build out the layout and UI of your app. To learn more, pour over the official Android documentation for UI, or check out our video course on layouts.
  • Keep coming back to raywenderlich.com. We’ve got some great Android content coming your way over the next days, weeks and months.
  • Talk to other developers. Make use of the forums below and ask questions, share your findings and pick up tips.

That’s all, folks! Give yourself a round of applause and stay tuned for more awesome tutorials from your Android team. :]

Average Rating

5/5

Add a rating for this content

3 ratings

Contributors

Comments