Статьи

Использование Android-преобразования текста в речь для создания Smart Assistant

В этом уроке я покажу вам, как создать простое приложение для Android, которое слушает речь пользователя и преобразует его в текст. Затем приложение проанализирует текст и использует его в качестве команды для хранения данных или ответа пользователя.

Пользовательский интерфейс приложения прост, всего одна ImageButton в центре полноэкранного градиентного фона. Каждый раз, когда пользователь говорит, он нажимает кнопку и говорит.

Вы можете найти окончательный проект на Github .

Создать проект

Создать приложение

Создайте новый проект в Android Studio, выбрав минимальный уровень API 18 и добавив пустое действие . Это будет единственное мероприятие в проекте.

Чтобы сделать просмотр полноэкранным, откройте AndroidManifest.xml и установите android:theme="@style/Theme.AppCompat.NoActionBar" . Это скроет ActionBar действий от нашей активности.

Теперь у вас есть полноэкранный белый макет с TextView внутри. Чтобы улучшить его, добавьте градиентную форму в RelativeLayout

Щелкните правой кнопкой мыши на папке для рисования и выберите New -> Drawable resource file . Назовите это ‘background’ и замените код следующим:

 <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:type="linear" android:startColor="#FF85FBFF" android:endColor="#FF008080" android:angle="45"/> </shape> 

Не стесняйтесь менять цвета и угол на ваш собственный.

Кнопка ImageButton внутри макета использует изображение из Material Design Icons . Загрузите и добавьте его как src .

Обновите код в файле activity_main.xml :

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/background" android:id="@+id/rel" tools:context="com.example.theodhor.speechapplication.MainActivity"> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/microphoneButton" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:src="@drawable/ic_mic_none_white_48dp" android:background="@null"/> </RelativeLayout> 

Говорящий

Теперь пользовательский интерфейс завершен, следующим шагом является Java-код внутри MainActivity .

TextToSpeech переменную TextToSpeech над методом onCreate :

 private TextToSpeech tts; 

Внутри onCreate добавить:

 tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() { @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { int result = tts.setLanguage(Locale.US); if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { Log.e("TTS", "This Language is not supported"); } speak("Hello"); } else { Log.e("TTS", "Initilization Failed!"); } } }); 

Это запускает службу TextToSpeech . Метод speak() принимает параметр String , представляющий собой текст, который вы хотите, чтобы Android говорил.

Создайте метод и добавьте этот код:

 private void speak(String text){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, null); }else{ tts.speak(text, TextToSpeech.QUEUE_FLUSH, null); } } 

Внутри Build.VERSION проверка Build.VERSION поскольку tts.speak(param,param,param) не рекомендуется для уровней API выше 5.1

После speak() создайте другой метод, чтобы остановить службу TextToSpeech когда пользователь закрывает приложение:

 @Override public void onDestroy() { if (tts != null) { tts.stop(); tts.shutdown(); } super.onDestroy(); } 

На этом этапе приложение говорит «Привет» после запуска. Следующий шаг — заставить его слушать.

Listening

Чтобы приложение слушалось, вы будете использовать кнопку микрофона. Добавьте этот код в onCreate :

 findViewById(R.id.microphoneButton).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listen(); } }); 

Нажатие на функцию ImageButton вызовет эту функцию:

 private void listen(){ Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Say something"); try { startActivityForResult(i, 100); } catch (ActivityNotFoundException a) { Toast.makeText(MainActivity.this, "Your device doesn't support Speech Recognition", Toast.LENGTH_SHORT).show(); } } 

Этот метод запускает listening которое отображается в виде диалога с текстовой подсказкой. Язык речи берется с устройства через метод Locale.getDefault() .

Метод startActivityForResult(i, 100) ожидает, пока текущее действие вернет результат. 100 — это произвольный код, прикрепленный к начальному действию, и может быть любым числом, которое подходит для вашего варианта использования. Когда результат возвращается из запущенного действия, он содержит этот код и использует его для различения нескольких результатов друг от друга.

Чтобы поймать результат от запущенного действия, добавьте этот переопределенный метод:

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == 100){ if (resultCode == RESULT_OK && null != data) { ArrayList<String> res = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); String inSpeech = res.get(0); recognition(inSpeech); } } } 

Этот метод перехватывает каждый результат, полученный в результате действия, и использует requestCode для результата распознавателя речи. Если resultCode равен 100 , resultCode равен OK и data из этого результата не равны null . Вы получаете строку result из res.get(0)

Создайте новый метод recognition который будет принимать String в качестве параметра:

 private void recognition(String text){ Log.e("Speech",""+text); } 

На этом этапе приложение может прослушивать после того, как пользователь нажимает кнопку микрофона, и преобразовывает речь пользователя в текст. Результат печатается в журнале ошибок .

Учусь

Чтобы сделать приложение более интересным, на этом шаге вы собираетесь сделать приложение способным изучать простые вещи, такие как ваше имя. Чтобы сделать это возможным, вам нужно использовать локальное хранилище.

Добавьте эти строки над методом onCreate :

 private SharedPreferences preferences; private SharedPreferences.Editor editor; private static final String PREFS = "prefs"; private static final String NAME = "name"; private static final String AGE = "age"; private static final String AS_NAME = "as_name"; 

Затем внутри onCreate добавьте:

 preferences = getSharedPreferences(PREFS,0); editor = preferences.edit(); 

Сначала вам нужно заставить приложение задать вопрос, поэтому поменяйте speak("Hello") на « speak("What is your name?")

Здесь вы можете использовать простую логику, поэтому, когда кто-то спрашивает: «Как вас зовут?», Вы получите ответ «Меня зовут Дори», взяв имя из ответа. Простой способ — разделить строку ответа пробелами (»«) и получить значение последнего индекса.

Обновите код в методе recognition :

 private void recognition(String text){ Log.e("Speech",""+text); //creating an array which contains the words of the answer String[] speech = text.split(" "); //the last word is our name String name = speech[speech.length-1]; //we got the name, we can put it in local storage and save changes editor.putString(NAME,name).apply(); //make the app tell our name speak("Your name is "+preferences.getString(NAME,null)); } 

Метод recognition использует все результаты из речи пользователя. Поскольку речь может отличаться, вы можете различать их, используя определенные слова, которые они могут содержать.

Например, код внутри этого метода может быть:

 private void recognition(String text){ Log.e("Speech",""+text); String[] speech = text.split(" "); //if the speech contains these words, the user is saying their name if(text.contains("my name is")){ String name = speech[speech.length-1]; Log.e("Your name", "" + name); editor.putString(NAME,name).apply(); speak("Your name is "+preferences.getString(NAME,null)); } } 

Но это все еще простое взаимодействие с приложением. Вы можете заставить его узнать свой возраст или даже дать ему имя.

Внутри того же метода, попробуйте эти простые условия:

 //This must be the age //Just speak: I am x years old. if(text.contains("years") && text.contains("old")){ String age = speech[speech.length-3]; Log.e("THIS", "" + age); editor.putString(AGE, age).apply(); } //Then ask it for your age if(text.contains("how old am I")){ speak("You are "+preferences.getString(AGE,null)+" years old."); } 

Приложение может сказать вам время:

 //Ask: What time is it? if(text.contains("what time is it")){ SimpleDateFormat sdfDate = new SimpleDateFormat("HH:mm");//dd/MM/yyyy Date now = new Date(); String[] strDate = sdfDate.format(now).split(":"); if(strDate[1].contains("00"))strDate[1] = "o'clock"; speak("The time is " + sdfDate.format(now)); } 

Умная речь

В проект GitHub я включил больше примеров, чтобы вы могли поэкспериментировать и создать свой собственный помощник для Android.

Надеюсь, вам понравился этот урок, и вы поговорили с вами по телефону. Любые вопросы или комментарии, пожалуйста, дайте мне знать ниже.