Icons and strings

If you’ve made it this far, you actually have a fully working Android app! If we wanted to, this app is pretty much ready to publish! Let’s add an icon and clean up the code a little bit:

  1. Right-click our res folder and select New → Image Asset
  2. Select “Launcher icon” from the dropdown menu at the top
  3. For “Asset type” (in the foreground layer tab), select “Image”, and select the highest-resolution version of our grim reaper icon (the one from drawable-xxxhdpi folder in the zip file).
  4. Play around with the settings until you find a setup you like, then press “Next” and “Finish”.
    • There’s a warning about overwriting some files. Those files are just the default icon, so don’t worry.
  5. Look through the res/drawable folder and delete any remaining XML versions of the old default icon.
    • What you need to delete depends on what options you selected. I only had two files to delete: ic_launcher_foreground.xml and ic_launcher_background.xml.

Run the app and enjoy the beautiful new icon on your home screen!

Now, let’s say this app gets really popular (haha… 😒), what to do if people ask us to translate it? The texts we display are scattered all across the code, and we really can’t start putting switch statements all over the place. The way to do language support in Android, is to place all strings in res/values/strings.xml. Android Studio also shows a warning whenever it detects that we display strings not in that file, and it can often extract the string for us automatically.

  1. Open activity_main.xml and click the orange “!” icon in the top-right corner of the layout designer.
  2. A panel with warnings appear. Expand the “Hardcoded text” warning, and click “Fix” at the bottom.
  3. In the dialog, give the string a name that makes it clear what this strings means even without any context. Then click OK.
    • This is important because translators often don’t see your app when translating it. This causes many bad translations when the same word can be used in different ways in the original language, but not the language being translated to.
    • Example: English “Empty” is used to tell the user that a folder doesn’t have anything in it, and for the text on the button that will delete everything inside the folder. In Norwegian, there are two different words for this: “Tom” og “Tøm”. Google made this mistake in the Gmail app.
    • To avoid these misunderstandings, use string resource names like action_empty, and label_is_empty, so translators can understand what the correct translation should be.
  4. The text in the layout is now replaced with @string/action_change_deadline or something like that, and if you look in res/values/strings.xml you should see this line:
    <string name="action_change_deadline">Change deadline</string>
  5. Replace any other strings you have in the layout using the same technique.

When you’re done, move on to MainActivity. Observe that most of the strings we display contain values we don’t know until the app is run. How would we translate that to languages where the syntax is “Hours left is X”?

The solution is use formatting strings! Let’s start with “X hours left”:

  1. Find the “X hours left” string (should be in updateUI()).
    Note: If you used Kotlin template strings, click the string, hit Alt+Enter and select “Convert to concatenated string”.
  2. Change it to the string becomes "%d hours left". %d indicates to translators that we’re going to insert a number.
  3. Press Alt+Enter and select “Extract strings resource”. Again, use a proper resource name, like label_hours_left.
    The whole line now looks something like this:

    hoursLeftTextView.text = hoursLeft.toString() + getString(R.string.label_hours_left)

    That’s better, but we’re not quite there.

  4. If you place the cursor just before that last ) and press Ctrl+P, you’ll see a popup telling you that getString() can take more arguments. These other arguments are the numbers we want inserted into the string. Put the number of hours left there, and remove it from the start of the string.
  5. Run the app. It should look exactly like last time you used it!

Rinse and repeat until you run out of strings.

If you want, you can translate the app by opening strings.xml, clicking “Open editor” at the end of the banner, clicking the globe 🌎 and selecting the language to translate to.

If you ever end up translating a real app, please avoid automated translations, especially for smaller languages. They produce gibberish like “Velg søknader som kjører under system støvel.” and you don’t even know about it.

Next: Displaying large lists (Kotlin)