Skip to content

Instantly share code, notes, and snippets.

@anhtuank7c
Created April 20, 2022 02:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anhtuank7c/b543fe4a59a801fa5c5547ccedd2d6e8 to your computer and use it in GitHub Desktop.
Save anhtuank7c/b543fe4a59a801fa5c5547ccedd2d6e8 to your computer and use it in GitHub Desktop.
AudioCue class, let initial this class to call speakOut function to speech the text.
package com.example;
import android.content.Context
import android.content.Context.AUDIO_SERVICE
import android.media.AudioAttributes
import android.media.AudioFocusRequest
import android.media.AudioManager
import android.os.Build
import android.os.Bundle
import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
import com.facebook.react.bridge.UiThreadUtil.runOnUiThread
import java.math.RoundingMode
import java.util.*
import kotlin.math.floor
class AudioCue(context: Context): TextToSpeech.OnInitListener, UtteranceProgressListener() {
private val settings = AudioCueSetting.getSavedSetting()
private var textToSpeech: TextToSpeech = TextToSpeech(context, this, "com.google.android.tts")
private val audioManager = context.getSystemService(AUDIO_SERVICE) as AudioManager
private var focusRequest: AudioFocusRequest? = null
private var ttsReady: Boolean = false
private var mContext: Context = context
companion object {
val supportedLanguages = listOf("ar", "da", "de", "en", "es", "fr", "it", "ja", "nb", "nl", "pl_PL", "pt", "sv")
}
init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val playbackAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
.build()
focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
.setAudioAttributes(playbackAttributes)
.setAcceptsDelayedFocusGain(false)
.setWillPauseWhenDucked(false)
.setOnAudioFocusChangeListener { focusChange ->
when (focusChange) {
AudioManager.AUDIOFOCUS_LOSS -> {
textToSpeech.stop()
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
textToSpeech.stop()
}
}
}
.build()
}
}
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
val result = textToSpeech.setLanguage(getCurrentLocale())
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
Logger.nonFatal(Throwable("The Language specified is not supported!"))
return
}
textToSpeech.setOnUtteranceProgressListener(this@AudioCue)
ttsReady = true
return
}
Logger.nonFatal(Throwable("Failed to initialization Text To Speech!"))
}
/**
* get default locale
* fallback to the English if current locale is not in supported languages list
*/
private fun getCurrentLocale(): Locale {
val language = Util.getLocale().toLowerCase()
if (supportedLanguages.contains(language)) {
return Locale(language)
}
return Locale.ENGLISH
}
private fun speakOut(message: String) {
if (!ttsReady) return
runOnUiThread {
val params = Bundle()
params.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_MUSIC)
val request = focusRequest
val result: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && request != null) {
audioManager.requestAudioFocus(request)
} else {
audioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
}
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
textToSpeech.speak(message, TextToSpeech.QUEUE_ADD, params, Date().time.toString())
}
}
}
private var mCallback: (() -> Unit)? = null
fun finish(callback: () -> Unit) {
mCallback = callback
textToSpeech.stop()
}
override fun onStop(utteranceId: String?, interrupted: Boolean) {
super.onStop(utteranceId, interrupted)
}
override fun onStart(utteranceId: String?) {
}
override fun onDone(utteranceId: String?) {
val request = focusRequest
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && request != null) {
audioManager.abandonAudioFocusRequest(request)
} else {
audioManager.abandonAudioFocus(null)
}
mCallback?.let { it() }
}
override fun onError(utteranceId: String?) {
mCallback?.let { it() }
}
}
@anhtuank7c
Copy link
Author

Usage example:

  val audioInstance = AudioCue(activityContextHere)
  audioInstance.speakOut("Hello world")
  audioInstance.finish()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment