An Android Hello World app with Kotlin

This tutorial assumes you have already download, installed, and configured Android Studio and either setup an Android Virtual Device, or have configured an Android Device for running applications

  1. Open Android Studio, closing any already open applications
  2. Choose the "Start a new Android Studio project" option
  3. Name the application "HelloWorld", and set the company domain as shown (you can use an alternative domain, but will need to adapt the project as appropriate at later stages). Ensure the save location is somewhere you will remember New Android project dialogue box
  4. Check the 'Include Kotlin Support' checkbox, then click 'Next'
  5. Select the Phone and Tablet option and choose API 14: Android 4.0 (IceCreamSandwich)
  6. Choose Empty Activity on the next screen and press 'Next'
  7. On the final screen, leave the Activity name as 'MainActivity' and the layout name as 'activity_main' and choose Finish. The IDE will take some time to build the project

Components of an Android Application

Android project navigator.An Android application is composed of various parts, these can be seen by expanding the folders in the project navigator. Key components include:

Creating the UI

  1. Open the activity_main.xml file. Depending on your IDEs settings, this will appear as either XML or a UI preview. If you see the preview, click the 'Text' tab, to the bottom left of the code area
  2. The Empty Activity which we created, is not actually completely empty, rather it contains a TextView with the text 'Hello World!'. In the XML this is visible as an element with a a number of properties. Identify the start and end of the tag in the XML
  3. Using the tab, switch to the Design view, select the textview, which will be in the middle of the UI, and delete it (use the delete key or the right click context menu)
  4. Switch back to the Text view, and observe that the element has been removed
  5. Return to the design view and ensure that AutoConnect is enabled - the icon should appear as shown here, and not with a line through it: autoconnect button
  6. Drag a new TextView from the Palette onto the view near the centre. Then reposition it so it is just below the blue bar at the top of the preview. It should appear to 'snap' into place and an arrow should appear between the TextView and the blue menu bar activity with a TextView
  7. Click the infer constraints button, so that the layout is inferred for all device sizes based on how you have positioned the TextView infer constrainst button
  8. With the TextView selected, in the Attributes pane to the right hand side of the IDE, change the ID to tvGreeting
  9. Next modify its text property in the attributes pane to say "Hello World". At this point we are hard-coding a string into our UI and the IDE will show a warning triangle at the top right of the UI preview pane.
  10. Click the warning and a message pane should appear below the design pane, as shown here: hard coded string warning
  11. Expand the message and you should see the full details, including a rationale for using a String resource. Click the 'Fix' button and click OK Extract String resource dialog box.
  12. Verify that the 'text' field in the Attributes pane has the value @string/hello_world
  13. Run the application and verify that it opens and shows the TextView with the phrase Hello World

Adding a button

  1. Add a button under the TextView and set its ID to btnGreet
  2. Ensure that the there is an arrow between the button and the greeting label. This arrow represents a 'constraint' and specified that it must be a certain distance below the label. Click the infer constraints button if needed.
  3. Set the text attribute to "Press me" then switch to the text view
  4. The newly added button should have an attribute highlighted in yellow in the XML, as we haven't defined a String resource for it. Select this line of code and a lightbulb should appear to the left hand side. Using the dropdown menu select the 'Extract string resource' option and choose OK on the dialogue box that appears. Extracting a String resource from XML

Making the button do something

  1. Open MainActivity.kt
  2. Modify the MainActivity class declaration so that it adopts the View.OnClickListener interface as follows
    class MainActivity : AppCompatActivity(), View.OnClickListener {
        //etc...
    }
  3. A warning line will be displayed under the class name, indicating that we've not implemented the methods required by the View.OnClickListener interface
  4. Add the following method to implement the method, initially with no implementation:
    override fun onClick(v: View?) {
        //handle button press
    }
  5. Next add the following line to the bottom of the onCreate method:
    btnGreet.setOnClickListener(this)
  6. Add this code to the onClick method to change the text of the textview on press of the button:
    tvGreeting.text = "Hello Android"
  7. Run the application to make sure that it functions as expected (the text should change to "Hello Android" when the button is tapped)
  8. The last line of code we added will have a warning, as we've added yet another hard-coded string to our application. Using the warning's corresponding 'lightbulb' indicator, select 'extract string resource' from the menu.
  9. Name the resource "hello_android", and save it
  10. Observe that the line of code now reads as follows:
    tvGreeting.text = getString(R.string.hello_android)
    This method can be used to obtain strings declared in resources programmatically.

Tidying up

Handling the correct button press

There are a couple of improvements that can be made. Firstly, you might be wondering how we would handle multiple buttons, as there is only one onClick method. As the view that is clicked is passed as a parameter into this method, we can check which one it is. The code for this would appear as follows:

if (v?.equals(btnGreet) == true) {
    tvGreeting.text = getString(R.string.hello_android)
}
The code needs a little explaining as it's unusual to need to write == true to check if a value or result of an expression is true. It's required in this case, because v represents a nullable View, and we have used a safe call (designated by ?.) to the equals method. The expression v?.equals(btnGreet) evaluates to a nullable Boolean, which will either be true, false or null. Because an if statement requires a non-nullable Boolean value (or expression), we have to check for equality with true

Simplifying the onClickListener syntax

We could leave it there, but there is a simpler way to add the on-click listener. The setOnClickListener method takes anything that implements the OnClickListener interface as it's parameter, so, rather than passing in the Activity we can declare an inline anonymous object which does the same. This results in code as follows:

btnGreet.setOnClickListener(object: View.OnClickListener{
    override fun onClick(v: View?){
        tvGreeting.text = getString(R.string.hello_android)
    }
})
The onClick method from the Activity, along with the interface adoption code should now be removed

This has already simplified our code somewhat, but we can simplify it further. Kotlin permits an optimisation whereby given a function that has an interface as it's parameter, if that interface has a single function, the function can be passed in instead, as follows:

btnGreet.setOnClickListener({
    view -> run {
    tvGreeting.text = getString(R.string.hello_android)
    }
})

This can be simplified even further as we are not using the view parameter it can be removed, and it is also permissible to remove the parentheses, thus the simplified version appears as follows:

btnGreet.setOnClickListener{
    tvGreeting.text = getString(R.string.hello_android) 
}

Excluding import statements, the code for the MainActivity class is as follows:

class MainActivity : AppCompatActivity(){

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnGreet.setOnClickListener{
            tvGreeting.text = getString(R.string.hello_android)
        }
    }
}

Internationalising the application

In order to truly appreciate the value of String resources, we will now internationalise our application

  1. Open the strings.xml file, which should show the Strings defined in our application. At the top right of the code pane, click the open editor link, this should show the following screen translations editor:
  2. Click the world icon at the top left of the pane, and select French (fr) in France (FR) from the list. An extra column should appear.)
  3. Add translations as shown here: translations editor with translations added
  4. Launch the application and in the settings in the virtual device, set French (for France) as the primary language and return to the app. Observe that the application (with the exception of it's name which was not changed) now displays text in French French version of Hello World app

A completed version of this Android Hello World application can be found on GitHub

Further task

Create a new Android application, similar to the one above, but with the addition of an EditText element above the Button. Add functionality so that the TextView displays "Hello World" by default (or its German equivalent if the device language is set to German), "Hello Android" if the button is pressed and the TextView is empty (again with German string provided), but, if the EditText contains user supplied text, display "Hello " followed by the user's name (or the German equivalent). Some further reading (and a translation service) may be required in order to do this.