In early 2011, a natural language understanding computer system called IBM Watson was able to beat all human contestants in a quiz-like game show called Jeopardy! It was an historic event and was perhaps the point when the general public started to realize that artificial intelligence was no longer the stuff of science fiction.
Back then, Watson ran on a supercomputer and could do little more than answer trivia questions. Today, however, it has been transformed into a far more versatile system, and a lot of its capabilities are available over the cloud.
In this series of tutorials, I'll show you how to use various services offered by the IBM Watson Developer Cloud in Android apps. In this introductory tutorial, you'll learn how to work with IBM Bluemix, the Watson Java SDK, and the Watson tone analyzer service to create a simple Android app that can identify the emotions present in any piece of text.
Prerequisites
To be able to follow along, you'll need:
- a recent version of Android Studio
- a free IBM Bluemix account
- and a device or emulator running Android 4.4 or higher
1. Creating a Watson Service
Watson's services can be accessed only through the IBM Bluemix cloud platform. That means you can use them in your application only after you've enabled them in the Bluemix console and acquired the required credentials.
Start by logging in to the console and navigating to Services > Watson.
Next, press the Create Watson service button to see all the Watson services that are available to you.
For now, because we're interested only in analyzing the emotional tone in written text, select the Tone Analyzer service.
On the next screen, change the name of the service to something meaningful and press the Create button.
The tone analyzer service will now be activated for your account, and a set of login credentials will be generated. To see what those credentials are, open the Service credentials tab and select the View credentials action.
Save the contents of the JSON document to a file on your computer. I suggest you name the file credentials.json.
2. Project Setup
The Watson Java SDK makes it very easy for you to communicate with any Watson service. To be able to use it in your project, add it as a compile
dependency in the app
module's build.gradle file.
compile 'com.ibm.watson.developer_cloud:java-sdk:3.7.2'
For this tutorial, you'll be needing two more libraries: Commons IO, to simplify file IO operations, and Android Design Support, to be able to use a few Material Design widgets. Add them too as compile
dependencies.
compile 'commons-io:commons-io:2.5' compile 'com.android.support:design:23.4.0'
You will also need the INTERNET
permission to communicate with IBM's servers, so add the following line to the AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET"/>
Finally, press the Sync Now button to complete the project configuration.
3. Initializing the Tone Analyzer
To communicate with Watson's tone analyzer service, you must use the ToneAnalyzer
class. Its constructor expects a date string as its argument, which it will use to automatically determine the version of the tone analyzer service to use.
final ToneAnalyzer toneAnalyzer = new ToneAnalyzer("2017-07-01");
Note that the date should always be a static string. This helps make sure that your app doesn't stop working when a new version of the service introduces breaking changes.
The ToneAnalyzer
instance must be configured to use your credentials, so move the credentials.json file, the one you created earlier in this tutorial, to your project's res/raw folder.
Next, you must extract the values of the username
and password
keys from the JSON file. The following code shows you how to do so quickly using the IOUtils
and JSONObject
classes:
JSONObject credentials = new JSONObject(IOUtils.toString( getResources().openRawResource(R.raw.credentials), "UTF-8" )); // Convert the file into a JSON object // Extract the two values String username = credentials.getString("username"); String password = credentials.getString("password");
You can now complete the configuration of the ToneAnalyzer
instance by calling the setUsernameAndPassword()
method.
toneAnalyzer.setUsernameAndPassword(username, password);
4. Creating a User Interface
Our app needs an interface that will allow the user to type in a few sentences and press a button to begin the tone analysis. In other words, you must now create a simple layout containing an EditText
widget and a Button
widget.
You can, optionally, also throw in a TextInputLayout
container to make sure that the EditText
widget conforms to the guidelines of Material Design.
Accordingly, add the following code to your activity's layout XML file:
<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:id="@+id/container"><EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Say something" android:id="@+id/user_input" android:lines="3"/></android.support.design.widget.TextInputLayout><Button android:text="Analyze Tone" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/container" android:id="@+id/analyze_button" />
5. Using the Tone Analyzer
The tone analysis must start as soon as the user presses the button. Therefore, you need to add an on-click event handler to the Button
widget using its setOnClickListener()
method. Before you do so, however, don't forget to get a reference to the widget using the findViewById()
method.
Button analyzeButton = (Button)findViewById(R.id.analyze_button); analyzeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // More code here } });
Inside the on-click event handler, the first thing you need to do is determine what the user has typed into the EditText
widget using its getText()
method.
EditText userInput = (EditText)findViewById(R.id.user_input); final String textToAnalyze = userInput.getText().toString();
Like all Watson services, the tone analyzer service offers a lot of different features. For instance, it can identify emotions, language style, and social tendencies in its input. It can also work with JSON documents, plain text, and HTML. Therefore, to use it efficiently, you must explicitly specify the features you need using a ToneOptions
object, which can be easily created using the ToneOptions.Builder
class.
For now, we'll be using the service only to list all the emotions that are present in a plain text string. Here's how you create a ToneOptions
object saying so:
ToneOptions options = new ToneOptions.Builder() .addTone(Tone.EMOTION) .html(false).build();
You can now compose a tone analysis request by calling the getTone()
method, which expects a string containing the text to analyze and a ToneOptions
object as its only arguments. To actually execute the request asynchronously, you must also call the enqueue()
method, which takes a ServiceCallback
instance as its argument.
toneAnalyzer.getTone(textToAnalyze, options).enqueue( new ServiceCallback<ToneAnalysis>() { @Override public void onResponse(ToneAnalysis response) { // More code here } @Override public void onFailure(Exception e) { e.printStackTrace(); } });
Inside the onResponse()
method of the ServiceCallback
class, you have access to a ToneAnalysis
object. By calling its getDocumentTone()
method, you can determine the overall tone of the text you passed to the service.
The return value of the getDocumentTone()
method is an ElementTone
object containing a list of tone categories. Because we explicitly stated earlier that we're interested only in the emotions category, the list will contain only one element. Accordingly, here's how you extract the scores for all the emotions the service detected:
List<ToneScore> scores = response.getDocumentTone() .getTones() .get(0) .getTones();
As you might expect, a ToneScore
object represents a single emotion. It has a Double
containing the actual score and a String
telling you the name of the emotion. If the score is greater than 0.5, it means that there's a good chance the emotion is being expressed in the text.
Let us now pick only those emotions whose scores are greater than 0.5 and use them to create a message that can be displayed to the user using a Toast
.
String detectedTones = ""; for(ToneScore score:scores) { if(score.getScore() > 0.5f) { detectedTones += score.getName() + " "; } } final String toastMessage = "The following emotions were detected:\n\n" + detectedTones.toUpperCase();
Because the onResponse()
method runs on different thread, you must make sure you create and display the Toast
only after calling the runOnUiThread()
method.
runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getBaseContext(), toastMessage, Toast.LENGTH_LONG).show(); } });
The app is now ready. If you run it, type in a few sentences, and start the analysis, you'll be able to see Watson accurately identify the emotions present in your text.
Conclusion
In this tutorial, you created an Android app that can use IBM Watson's tone analyzer service to perform the complex task of guessing the emotions expressed in a piece of text. You also learned the basics of using the Watson Java SDK and the IBM Bluemix console.
To learn more about the service, you can refer to its official documentation.
In the meantime, you can check out some of our other posts on using machine learning for your Android apps right here on Envato Tuts+!
- Android ThingsAndroid Things and Machine Learning
- Android ThingsAndroid Things: Creating a Cloud-Connected Doorman
- Android SDKHow to Use Google Cloud Machine Learning Services for Android
- Android SDKCreate an Intelligent App With Google Cloud Speech and Natural Language APIs
- Android SDKHow to Use the Google Cloud Vision API in Android Apps