Build a basic messaging style app

This codelab is activity #2 in the Get started with mobile text classification pathway.

In this codelab, you'll build a simple messaging app. Later in the pathway, you'll update this app with a machine learning model that will filter unwanted spam from the messages on the app.

Prerequisites

  • A basic knowledge of Android development with Kotlin, and (optionally) iOS development with Swift

What you'll build

  • A simple messaging app

What you'll need

  • For Android, to get started you'll need Android Studio. Please make sure it's installed and fully updated before continuing.
  • For iOS, you'll need Xcode. You can find this in the App Store. (If you want to write the iOS app only, skip straight to step 5.

Get the Code

If you don't want to follow step-by-step, and just see the final code for this pathway, it's at

git clone https://github.com/googlecodelabs/odml-pathways

In here, find the TextClassificationOnMobile directory, and within these you'll see the Android and iOS sub directories. These directories will contain TextClassificationStep1 sub directories, which contain the app on Android and iOS respectively.

968cc631a448a8ef.png

  1. Launch Android Studio.

4542b16e14c33eed.png

  1. Select Create New Project. You'll see a dialog that asks you to select a Project Template.
  2. Select Empty Activity and click Next. You'll next be asked to Configure your project. Choose whatever you like, but ensure that the language is Kotlin, and the Minimum SDK is API 23.
  3. Click Finish. Once this is done, Android Studio will open with your project. It may take a few moments for it to perform a gradle sync to make sure everything is in order, particularly if this is your first time using Android Studio.

The user interface for an Android app is created using an XML file called a layout file.

  1. Open the file. Click app > res > layout > activity_main.xml using the explorer in Android Studio.

562f935ccaa9e666.png

On the top right hand side of the screen, you should see a selection that has tabs for Code, Split and Design, like this:

3ae858bfe4ec100f.png

Make sure that ‘Code' is selected before moving to the next step.

  1. Replace the code with this XML:
<?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">

 <LinearLayout android:orientation="vertical"
      android:layout_height="match_parent"
      android:layout_width="match_parent">
      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:orientation="horizontal">
          <TextView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Enter a string:"></TextView>
          <EditText
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/txtInput"></EditText>

      </LinearLayout>

      <TextView
          android:id="@+id/txtOutput"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="Output Goes here"
          android:textSize="36sp"></TextView>
     <Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:id="@+id/btnSendText"
          android:text="Send"></Button>

 </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

This gives you a basic user interface containing an input area with a TextView, prompting you to Enter a String and an EditText called txtInput that can be used to enter a string. Beneath it is a TextView that will render the output, and a button that the user will press to trigger the classification.

The next step is to write the code that will activate this user interface.

You can edit the code for this activity by finding the MainActivity code file.

  1. In Android Studio, click app > java > MainActivity.

c633c2293d0835b8.png

  1. Open the MainActivity file to get to the code editor. Replace everything in this file except the first line that starts with ‘package' with this code:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView

class MainActivity : AppCompatActivity() {
    lateinit var txtInput: EditText
    lateinit var btnSendText: Button
    lateinit var txtOutput: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        txtInput = findViewById(R.id.txtInput)
        txtOutput = findViewById(R.id.txtOutput)
        btnSendText = findViewById(R.id.btnSendText)
        btnSendText.setOnClickListener {
            var toSend:String = txtInput.text.toString()
            txtOutput.text = toSend
        }
    }
}

This code connects the controls on the layout to txtInput, txtOutput and btnSendText so they can be addressed in code. Then, it sets up an OnClickListener for the button, so that when the user touches it, the text from txtInput will be read, converted into a String, and then the txtOutput.text property is set to that string.

The following steps require some familiarity with Xcode and iOS development with Swift.

If you don't want to go through the creation process, you can clone the repo and open the app directly. It's called TextClassificationStep1, and it's in the iOS folder in the repo.

To create the basic app, you'll start with Xcode.

  1. Create a new App using the basic template:

254c026ac66e32f9.png

  1. Choose options for your new project. Give your product a Name and an Organization Identifier. You can type what you'd like, or follow along with the example below: (But be sure to set the interface to Storyboard and the Life Cycle to UIKitApp Delegate, as shown.)

d0bd704bfa657d5f.png

  1. Open Main.storyboard. You'll see a design surface on which you can add controls.
  2. To add controls, click the + button at the top of the Xcode window.

a5203e9757e6b11e.png

  1. Use this to place a TextView control, a Button control, and a Label control onto the design surface. It should look something like this:

13d02aae8d8c4a13.png

  1. Use the assistant to open a side-by-side view with the storyboard and the ViewController.swift files both open. The assistant is a small icon at the upper right of the screen, as shown here:

d152cce014151f26.png

  1. Press the CONTROL key, and drag the TextView control over to the code surface. You should see a blue arrow as you drag.
  2. Drop onto the code just below the class declaration. You'll get a popup asking you the connection type. It should look something like this:

455b8b131e5f3b3d.png

  1. Select Outlet and give it the name txtInput.
  2. Do the same for the label, then make the connection type an Outlet, and give it the name txtOutput.
  3. Finally, drag the button over, but this time select Action as the connection type. (Do not use Outlet as the connection type.)
  4. Name the action btnSendText.

When you're done, your code at the top of the class should look like this:

@IBOutlet weak var txtInput: UITextView!
@IBOutlet weak var txtOutput: UILabel!
@IBAction func btnSendText(_ sender: Any) {
}

As this view uses a UITextView, in order to have it respond to events on this view, it needs to be a UITextViewDelegate.

You can get this by changing the class declaration to this:

class ViewController: UIViewController, UITextViewDelegate {

Then, in the viewDidLoad function, set the delegate for the UITextView (which you called txtInput when you set up the outlet) to this class like this:

override func viewDidLoad() {
    super.viewDidLoad()
    txtInput.delegate = self
}

Finally you want to handle removing the keyboard from display once the user presses Enter on the keyboard. This is done through the delegation you just set up, and you can implement this method on the ViewController to handle it.

func textView(_ textView: UITextView, shouldChangeTextIn range: 
              NSRange, replacementText text: String) -> Bool {
    if (text == "\n") {
        textView.resignFirstResponder()
        return false
    }
    return true
}

For this app the button action is trivial, we'll just pass through what the user types to the output. Later you'll see how an NLP model can filter this text. But for now, let's just wire it up to simulate a passthrough.

You already created the action btnSendText, so now all you need to do is add the code to that:

@IBAction func btnSendText(_ sender: Any) {
    txtOutput.text = "Sent :" + txtInput.text
}

You've now completed this codelab!

Next in the pathway, you'll learn how to create an NLP model, which you'll later bring back to this app to equip it to filter your user's text for comment spam!