Android SDK: Erstellen Sie eine Speak and Repeat-App
German (Deutsch) translation by Katharina Grigorovich-Nevolina (you can also view the original English article)
Die Android-Plattform unterstützt sowohl die Spracherkennung als auch die Sprachsynthese. In diesem Tutorial erstellen wir eine einfache Android-App, mit der der Benutzer sprechen kann, versucht zu erkennen, was er sagt, und dann wiederholt, was er mithilfe der Text-zu-Sprache-Engine erkannt hat.
Wir werden für die TTS-Engine dieselbe Technik verwenden wie im Android SDK: Verwenden der Text-to-Speech-Engine, daher liegt der Schwerpunkt dieses Tutorials auf dem Spracherkennungselement. Sowohl die Spracherkennung als auch die Sprachsynthese sind auf der Android-Plattform relativ einfach zu implementieren. Daher sollten Sie die Schritte in diesem Tutorial auch dann ausführen können, wenn Sie ein Android-Anfänger sind.
Schritt 1: Starten Sie ein Android-Projekt
Erstellen Sie ein neues Android-Projekt in Eclipse. Wenn Sie die Spracherkennungsfunktion in einer vorhandenen App implementieren möchten, öffnen Sie sie stattdessen. Für dieses Tutorial haben wir eine SDK-Mindestversion von 8, und Sie müssen keine besonderen Ergänzungen zu Ihrer Manifest-Datei vornehmen. Der Standardinhalt sollte ausreichen.
Schritt 2: Definieren Sie die Benutzeroberfläche
Beginnen wir mit der Definition der Benutzeroberfläche. Beim Start der App wird dem Benutzer eine Schaltfläche angezeigt. Beim Drücken der Taste fordert die App sie zum Sprechen auf und wartet auf ihre Spracheingabe. Wenn das Spracherkennungsprogramm die Spracheingabe verarbeitet, zeigt die App dem Benutzer eine Liste der vorgeschlagenen Wörter an. Wie Sie wissen, ist die Erkennung nicht immer korrekt, wenn Sie als Benutzer die Spracherkennung ausprobiert haben. Daher ist diese Liste unerlässlich. Wenn der Benutzer ein Element aus der Liste auswählt, spricht die App es mithilfe der TTS-Engine an ihn zurück. Der TTS-Teil der Anwendung ist optional, sodass Sie ihn bei Bedarf weglassen können.
Die App wird einige Textzeichenfolgen als Teil der Benutzeroberfläche verwenden. Definieren Sie sie daher, indem Sie die Datei "res/values/strings.xml" öffnen und den folgenden Inhalt eingeben:
1 |
<resources>
|
2 |
<string name="intro">Press the button to speak!</string> |
3 |
<string name="app_name">SpeechRepeat</string> |
4 |
<string name="speech">Speak now!</string> |
5 |
<string name="word_intro">Suggested words…</string> |
6 |
</resources>
|
Natürlich können Sie den String-Inhalt beliebig ändern.
Öffnen Sie Ihre Datei "res/layout/main.xml", um das Haupt-App-Layout zu erstellen. Wechseln Sie zum XML-Editor, wenn der grafische Editor standardmäßig angezeigt wird. Geben Sie ein lineares Layout als Hauptlayout für die Startaktivität der App ein:
1 |
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" |
2 |
android:layout_width="fill_parent" |
3 |
android:layout_height="fill_parent" |
4 |
android:orientation="vertical" |
5 |
android:background="#ff330066" |
6 |
android:paddingBottom="5dp" > |
7 |
|
8 |
</LinearLayout>
|
Das lineare Layout enthält verschiedene Stildeklarationen, einschließlich einer Hintergrundfarbe. Geben Sie im linearen Layout zunächst eine informative Textansicht ein:
1 |
<TextView android:layout_width="fill_parent" |
2 |
android:layout_height="wrap_content" |
3 |
android:text="@string/intro" |
4 |
android:padding="5dp" |
5 |
android:textStyle="bold" |
6 |
android:textSize="16dp" |
7 |
android:gravity="center" |
8 |
android:textColor="#ffffff33" /> |
Beachten Sie, dass sich die Textansicht auf eine der von uns definierten Zeichenfolgen bezieht. Außerdem werden verschiedene Anzeigeeigenschaften festgelegt, die Sie bei Bedarf ändern können. Fügen Sie nach der Textansicht eine Schaltfläche hinzu:
1 |
<Button android:id="@+id/speech_btn" |
2 |
android:layout_width="match_parent" |
3 |
android:layout_height="wrap_content" |
4 |
android:text="@string/speech" /> |
Der Benutzer drückt diese Taste, um zu sprechen. Wir geben der Schaltfläche eine ID, damit wir sie im Java-Code identifizieren und eine der darauf definierten Zeichenfolgen anzeigen können. Fügen Sie nach der Schaltfläche eine weitere informative Textansicht hinzu, die der Liste der vorgeschlagenen Wörter vorangestellt wird:
1 |
<TextView android:layout_width="fill_parent" |
2 |
android:layout_height="wrap_content" |
3 |
android:padding="5dp" |
4 |
android:text="@string/word_intro" |
5 |
android:textStyle="italic" /> |
Auch diese Textansicht verwendet eine String-Ressource und enthält Stileigenschaften. Das letzte Element in unserem linearen Layout main.xml ist die Liste der vorgeschlagenen Wörter:
1 |
<ListView android:id="@+id/word_list" |
2 |
android:layout_width="fill_parent" |
3 |
android:layout_height="0dip" |
4 |
android:layout_weight="1" |
5 |
android:paddingLeft="10dp" |
6 |
android:paddingTop="3dp" |
7 |
android:paddingRight="10dp" |
8 |
android:paddingBottom="3dp" |
9 |
android:layout_marginLeft="20dp" |
10 |
android:layout_marginRight="20dp" |
11 |
android:layout_marginTop="5dp" |
12 |
android:layout_marginBottom="5dp" |
13 |
android:background="@drawable/words_bg" /> |
Die Listenansicht wird beim Ausführen der App mit Daten gefüllt, daher geben wir ihr eine ID zur Identifizierung in Java. Das Element bezieht sich auch auf eine zeichnbare Ressource, die Sie jedem der zeichnbaren Ordner im Verzeichnis "res" Ihrer App hinzufügen, als "words_bg.xml" speichern und den folgenden Inhalt eingeben sollten:
1 |
<shape xmlns:android="http://schemas.android.com/apk/res/android" |
2 |
android:dither="true"> |
3 |
<gradient
|
4 |
android:startColor="#ff000000" |
5 |
android:endColor="#ff000000" |
6 |
android:centerColor="#00000000" |
7 |
android:angle="180" /> |
8 |
<corners android:radius="10dp" /> |
9 |
<stroke
|
10 |
android:width="2dp" |
11 |
android:color="#66ffffff" /> |
12 |
</shape>
|
Das ist eine einfache Form, die hinter der Listenansicht angezeigt werden kann. Sie können das und die Stileigenschaften der Listenansicht natürlich ändern, wenn Sie dies wünschen. Das einzige verbleibende Element der Benutzeroberfläche, das wir jetzt definieren müssen, ist das Layout für ein einzelnes Element in der Liste, von dem jedes einen Wortvorschlag anzeigt. Erstellen Sie eine neue Datei in "res/layout" mit dem Namen "word.xml" und geben Sie den folgenden Code ein:
1 |
<TextView xmlns:android="http://schemas.android.com/apk/res/android" |
2 |
android:layout_width="fill_parent" |
3 |
android:layout_height="fill_parent" |
4 |
android:gravity="center" |
5 |
android:padding="5dp" |
6 |
android:textColor="#ffffffff" |
7 |
android:textSize="16dp" > |
8 |
</TextView>
|
Jedes Element in der Liste ist eine einfache Textansicht. Damit ist unser Interface-Design abgeschlossen. So erscheint die App beim ersten Start:


Hinweis: Machen Sie sich keine Sorgen über das fehlende Dithering. So sieht es im DDMS-Screenshot aus. Auf dem Gerät selbst ist der Gradient perfekt glatt.
Schritt 3: Einrichten der Spracherkennung
Jetzt können wir Ihren Java-Code implementieren. Öffnen Sie die Hauptaktivität Ihrer App und fügen Sie oben die folgenden Importanweisungen hinzu:
1 |
import java.util.ArrayList; |
2 |
import java.util.List; |
3 |
import java.util.Locale; |
4 |
|
5 |
import android.app.Activity; |
6 |
import android.content.Intent; |
7 |
import android.content.pm.PackageManager; |
8 |
import android.content.pm.ResolveInfo; |
9 |
import android.os.Bundle; |
10 |
import android.speech.RecognizerIntent; |
11 |
import android.speech.tts.TextToSpeech.OnInitListener; |
12 |
import android.speech.tts.TextToSpeech; |
13 |
import android.util.Log; |
14 |
import android.view.View; |
15 |
import android.view.View.OnClickListener; |
16 |
import android.widget.AdapterView; |
17 |
import android.widget.AdapterView.OnItemClickListener; |
18 |
import android.widget.ArrayAdapter; |
19 |
import android.widget.Button; |
20 |
import android.widget.ListView; |
21 |
import android.widget.Toast; |
22 |
import android.widget.TextView; |
Möglicherweise benötigen Sie nicht alle diese Funktionen, wenn Sie die TTS-Funktionalität nicht implementieren. Eclipse sollte Importe hervorheben, die Sie nicht verwendet haben. Überprüfen Sie sie daher, wenn Sie mit dem Codieren fertig sind. Erweitern Sie Ihre Deklarationszeile für die Eröffnungsklasse wie folgt und ändern Sie den Aktivitätsnamen entsprechend Ihren eigenen:
1 |
public class SpeechRepeatActivity extends Activity implements OnClickListener, OnInitListener { |
Der "OnInitListener" wird nur für die TTS-Funktion benötigt. Fügen Sie Ihrer Klassendeklaration vor der Methode "onCreate" die folgenden Instanzvariablen hinzu:
1 |
//voice recognition and general variables
|
2 |
|
3 |
//variable for checking Voice Recognition support on user device
|
4 |
private static final int VR_REQUEST = 999; |
5 |
|
6 |
//ListView for displaying suggested words
|
7 |
private ListView wordList; |
8 |
|
9 |
//Log tag for output information
|
10 |
private final String LOG_TAG = "SpeechRepeatActivity";//***enter your own tag here*** |
11 |
|
12 |
//TTS variables
|
13 |
|
14 |
//variable for checking TTS engine data on user device
|
15 |
private int MY_DATA_CHECK_CODE = 0; |
16 |
|
17 |
//Text To Speech instance
|
18 |
private TextToSpeech repeatTTS; |
In Ihrer "onCreate"-Methode sollte Ihre Klasse bereits die Superclass-Methode aufrufen und Ihr Hauptlayout festlegen. Wenn nicht, sollte es so beginnen:
1 |
//call superclass
|
2 |
super.onCreate(savedInstanceState); |
3 |
//set content view
|
4 |
setContentView(R.layout.main); |
Rufen Sie als Nächstes noch in Ihrer "onCreate" -Methode einen Verweis auf die von uns erstellte Sprachschaltfläche und Liste mit ihren ID-Werten ab:
1 |
//gain reference to speak button
|
2 |
Button speechBtn = (Button) findViewById(R.id.speech_btn); |
3 |
//gain reference to word list
|
4 |
wordList = (ListView) findViewById(R.id.word_list); |
Die Listenansicht ist eine Instanzvariable, auf die in der gesamten Klasse zugegriffen werden kann. Jetzt müssen wir herausfinden, ob das Benutzergerät Spracherkennungsunterstützung bietet:
1 |
//find out whether speech recognition is supported
|
2 |
PackageManager packManager = getPackageManager(); |
3 |
List<ResolveInfo> intActivities = packManager.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0); |
4 |
if (intActivities.size() != 0) { |
5 |
//speech recognition is supported - detect user button clicks
|
6 |
speechBtn.setOnClickListener(this); |
7 |
}
|
8 |
else
|
9 |
{
|
10 |
//speech recognition not supported, disable button and output message
|
11 |
speechBtn.setEnabled(false); |
12 |
Toast.makeText(this, "Oops - Speech recognition not supported!", Toast.LENGTH_LONG).show(); |
13 |
}
|
Wir fragen die Umgebung ab, um festzustellen, ob die Erkennungsabsicht vorhanden ist. Wenn dies der Fall ist, weisen wir die App an, auf den Benutzer zu hören, der die Sprachtaste drückt. Wenn die Spracherkennung nicht unterstützt wird, deaktivieren wir einfach die Schaltfläche und geben eine informative Nachricht an den Benutzer aus.
Schritt 4: Hören Sie auf Spracheingabe
Lassen Sie uns den Klick-Listener für die Sprachschaltfläche einrichten, für die wir die App angewiesen haben, Klicks zu erkennen. Fügen Sie außerhalb der "onCreate"-Methode, aber innerhalb Ihrer Activity-Klassendeklaration eine "onClick"-Methode wie folgt hinzu:
1 |
/**
|
2 |
* Called when the user presses the speak button
|
3 |
*/
|
4 |
public void onClick(View v) { |
5 |
if (v.getId() == R.id.speech_btn) { |
6 |
//listen for results
|
7 |
listenToSpeech(); |
8 |
}
|
9 |
}
|
Implementieren Sie nun die Methode, die wir hier nach der "onClick"-Methode aufgerufen haben:
1 |
/**
|
2 |
* Instruct the app to listen for user speech input
|
3 |
*/
|
4 |
private void listenToSpeech() { |
5 |
|
6 |
//start the speech recognition intent passing required data
|
7 |
Intent listenIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); |
8 |
//indicate package
|
9 |
listenIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getClass().getPackage().getName()); |
10 |
//message to display while listening
|
11 |
listenIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Say a word!"); |
12 |
//set speech model
|
13 |
listenIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); |
14 |
//specify number of results to retrieve
|
15 |
listenIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 10); |
16 |
|
17 |
//start listening
|
18 |
startActivityForResult(listenIntent, VR_REQUEST); |
19 |
}
|
Ein Teil dieses Codes ist Standard zum Einrichten der Spracherkennungs-Hörfunktion. Bereiche, die besonders beachtet werden müssen, um die Zeile einzuschließen, in der wir "EXTRA_PROMPT" angeben - Sie können dies ändern, um Text einzuschließen, der angezeigt werden soll, um den Benutzer zum Sprechen aufzufordern. Beachten Sie auch die Zeile "EXTRA_MAX_RESULTS", in der wir angeben, wie viele Vorschläge der Erkenner zurückgeben soll, wenn der Benutzer spricht. Da wir die Methode "startActivityForResult" aufrufen, werden die Erkennungsergebnisse in der Methode "onActivityResult" behandelt.
Wenn die App auf Benutzersprache wartet, wird Folgendes angezeigt:


Schritt 5: Präsentieren Sie Wortvorschläge
Implementieren Sie die Methode "onActivityResult" in Ihrer Klassendeklaration wie folgt:
1 |
/**
|
2 |
* onActivityResults handles:
|
3 |
* - retrieving results of speech recognition listening
|
4 |
* - retrieving result of TTS data check
|
5 |
*/
|
6 |
@Override
|
7 |
protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
8 |
//check speech recognition result
|
9 |
if (requestCode == VR_REQUEST && resultCode == RESULT_OK) |
10 |
{
|
11 |
//store the returned word list as an ArrayList
|
12 |
ArrayList<String> suggestedWords = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); |
13 |
//set the retrieved list to display in the ListView using an ArrayAdapter
|
14 |
wordList.setAdapter(new ArrayAdapter<String> (this, R.layout.word, suggestedWords)); |
15 |
}
|
16 |
|
17 |
//tss code here
|
18 |
|
19 |
//call superclass method
|
20 |
super.onActivityResult(requestCode, resultCode, data); |
21 |
}
|
Hier rufen wir das Ergebnis des Spracherkennungsprozesses ab. Beachten Sie, dass die "if"-Anweisung prüft, ob der Anforderungscode die Variable ist, die wir beim Aufruf von "startActivityForResult" übergeben haben. In diesem Fall wissen wir, dass diese Methode aufgrund der abhörenden Absicht aufgerufen wird. Der Erkenner gibt die Liste der 10 vorgeschlagenen Wörter zurück, die wir als Array-Liste speichern. Anschließend füllen wir die Listenansicht mit diesen Wörtern, indem wir ein Array-Adapter-Objekt als Adapter für die Ansicht festlegen. Jetzt zeigt jedes der Elemente in der Listenansicht eines der vorgeschlagenen Wörter an.
Wenn die App die Benutzereingabesprache erfolgreich erkennt und die Liste der Wörter zurückgibt, wird sie wie folgt angezeigt:


Wenn die App die Benutzereingabe nicht erkennt, wird alternativ der folgende Bildschirm angezeigt:


Schritt 6: Benutzerwortauswahl erkennen
Wir möchten den Benutzer erkennen, der Wörter aus der Liste auswählt. Implementieren wir daher einen Klick-Listener für die Listenelemente. Zurück in Ihrer "onCreate"-Methode legen Sie nach dem vorhandenen Code den Listener für jedes Element in der Liste wie folgt fest:
1 |
//detect user clicks of suggested words
|
2 |
wordList.setOnItemClickListener(new OnItemClickListener() { |
3 |
|
4 |
//click listener for items within list
|
5 |
public void onItemClick(AdapterView<?> parent, View view, int position, long id) |
6 |
{
|
7 |
//cast the view
|
8 |
TextView wordView = (TextView)view; |
9 |
//retrieve the chosen word
|
10 |
String wordChosen = (String) wordView.getText(); |
11 |
//output for debugging
|
12 |
Log.v(LOG_TAG, "chosen: "+wordChosen); |
13 |
//output Toast message
|
14 |
Toast.makeText(SpeechRepeatActivity.this, "You said: "+wordChosen, Toast.LENGTH_SHORT).show();//**alter for your Activity name*** |
15 |
}
|
16 |
});
|
Wir verwenden die Methode "setOnItemClickListener", um jedem Element in der Liste einen Listener zuzuweisen. Im neuen "OnItemClickListener" implementieren wir die "onItemClick"-Methode, um auf diese Klicks zu reagieren. Diese Methode wird ausgelöst, wenn der Benutzer ein vorgeschlagenes Wort aus der Liste auswählt. Zuerst wandeln wir die angeklickte Ansicht in eine Textansicht um und rufen dann den Text daraus ab. Dieser Text ist das Wort, das der Benutzer ausgewählt hat. Wir schreiben das ausgewählte Wort zum Testen in das Protokoll und geben es als Toast-Nachricht an den Benutzer zurück. Abhängig von den Anforderungen Ihrer eigenen Anwendung möchten Sie möglicherweise das ausgewählte Wort weiterverarbeiten - dieser Code dient lediglich der Demonstration.
Der Benutzer kann den Touchscreen drücken oder einen Trackball verwenden, um Wörter in der Liste auszuwählen.


Wenn der Benutzer ein Wort auswählt, wird die Toast-Nachricht angezeigt, die es bestätigt.


Schritt 7: Einrichten der TTS-Funktionalität
Wenn Sie die Text-to-Speech-Funktion nicht implementieren möchten, können Sie jetzt anhalten und Ihre App testen. Wir benötigen nur ein wenig mehr Verarbeitung, damit unsere App das vom Benutzer gewählte Wort wiederholt. Um die TTS-Engine einzurichten, fügen Sie zunächst den folgenden Code zu dem Abschnitt in Ihrer "onCreate" -Methode hinzu, in dem Sie das System nach Spracherkennungsunterstützung abgefragt haben. Innerhalb der "if"-Anweisung nach "languageBtn.setOnClickListener (this);":
1 |
//prepare the TTS to repeat chosen words
|
2 |
Intent checkTTSIntent = new Intent(); |
3 |
//check TTS data
|
4 |
checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); |
5 |
//start the checking Intent - will retrieve result in onActivityResult
|
6 |
startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE); |
Wie beim Abhören von Sprache erhalten wir das Ergebnis dieser Codeprüfung für TTS-Daten in der Methode "onActivityResult". Fügen Sie in dieser Methode vor der Zeile, in der wir die Oberklasse "onActivityResult"-Methode aufrufen, Folgendes hinzu:
1 |
//returned from TTS data check
|
2 |
if (requestCode == MY_DATA_CHECK_CODE) |
3 |
{
|
4 |
//we have the data - create a TTS instance
|
5 |
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) |
6 |
repeatTTS = new TextToSpeech(this, this); |
7 |
//data not installed, prompt the user to install it
|
8 |
else
|
9 |
{
|
10 |
//intent will take user to TTS download page in Google Play
|
11 |
Intent installTTSIntent = new Intent(); |
12 |
installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); |
13 |
startActivity(installTTSIntent); |
14 |
}
|
15 |
}
|
Hier initialisieren wir das TTS, wenn die Daten bereits installiert sind, andernfalls fordern wir den Benutzer auf, sie zu installieren. Weitere Anleitungen zur Verwendung der TTS-Engine finden Sie im Android SDK: Verwenden des Text-to-Speech-Engine-Tutorials.
Um das TTS-Setup abzuschließen, fügen Sie Ihrer Klassendeklaration die Methode "onInit" hinzu und behandeln Sie die Initialisierung des TTS wie folgt:
1 |
/**
|
2 |
* onInit fires when TTS initializes
|
3 |
*/
|
4 |
public void onInit(int initStatus) { |
5 |
//if successful, set locale
|
6 |
if (initStatus == TextToSpeech.SUCCESS) |
7 |
repeatTTS.setLanguage(Locale.UK);//***choose your own locale here*** |
8 |
}
|
Hier legen wir einfach das Gebietsschema für das TTS fest, aber Sie können auch andere Setup-Aufgaben ausführen, wenn Sie möchten.
Schritt 8: Wiederholen Sie die Benutzerauswahl
Schließlich können wir das vom Benutzer gewählte Wort wiederholen. Zurück in Ihrer "onCreate"-Methode, innerhalb der "OnItemClickListener"-Methode "onItemClick", fügen Sie nach der Zeile, in der wir eine Toast-Nachricht ausgeben, Folgendes hinzu:
1 |
//speak the word using the TTS
|
2 |
repeatTTS.speak("You said: "+wordChosen, TextToSpeech.QUEUE_FLUSH, null); |
Dadurch wiederholt die App das vom Benutzer ausgewählte Wort als Teil einer einfachen Phrase. Das geschieht gleichzeitig mit der Meldung Toast.
Schlussfolgerung
Das ist unsere komplette Speak and Repeat App. Testen Sie es auf einem Android-Gerät mit Spracherkennung und TTS-Unterstützung. Der Emulator unterstützt keine Spracherkennung. Sie müssen diese Funktionalität daher auf einem tatsächlichen Gerät testen. Der Quellcode ist beigefügt, sodass Sie überprüfen können, ob Sie alles am richtigen Ort haben. Natürlich können Ihre eigenen Apps die Spracherkennung als Teil einer anderen Verarbeitung implementieren, aber dieses Tutorial sollte Sie mit den Grundlagen der Unterstützung der Spracheingabe ausgestattet haben.



