Compatibility with Android 10
Refresh GUI
This commit is contained in:
@ -1,26 +1,38 @@
|
||||
package adrienmalin.pingpoints
|
||||
|
||||
import android.arch.lifecycle.ViewModelProviders
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.speech.RecognitionListener
|
||||
import android.speech.RecognizerIntent
|
||||
import android.speech.SpeechRecognizer
|
||||
import android.speech.tts.TextToSpeech
|
||||
import android.speech.tts.UtteranceProgressListener
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.app.AppCompatDelegate
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import java.util.regex.Pattern
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
class MatchActivity : AppCompatActivity() {
|
||||
var matchModel: MatchModel? = null
|
||||
var match: MatchModel? = null
|
||||
var textScore: android.widget.TextView? = null
|
||||
var textService: android.widget.TextView? = null
|
||||
var buttons: Array<Button> = emptyArray()
|
||||
var imageViews: Array<ImageView> = emptyArray()
|
||||
var icStt: ImageView? = null
|
||||
var tts: TextToSpeech? = null
|
||||
var stt: SpeechRecognizer? = null
|
||||
|
||||
|
||||
inner class WaitForTtsInit : TextToSpeech.OnInitListener {
|
||||
override fun onInit(status: Int) {
|
||||
@ -28,58 +40,91 @@ class MatchActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
inner class SttAfterTts : UtteranceProgressListener() {
|
||||
inner class WaitForTtsSpeak : UtteranceProgressListener() {
|
||||
override fun onDone(id: String) {
|
||||
SttDialog().show(supportFragmentManager, "SttDialog")
|
||||
runOnUiThread {
|
||||
startSTT()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart(id: String) {}
|
||||
|
||||
@Suppress("OverridingDeprecatedMember")
|
||||
override fun onError(id: String) {}
|
||||
}
|
||||
|
||||
inner class SttListener : RecognitionListener {
|
||||
var minRms: Float = 0f
|
||||
var maxRms: Float = 0f
|
||||
|
||||
override fun onReadyForSpeech(arg0: Bundle?) {
|
||||
icStt?.alpha = .5f
|
||||
}
|
||||
|
||||
override fun onBeginningOfSpeech() {}
|
||||
|
||||
override fun onBufferReceived(buffer: ByteArray?) {}
|
||||
|
||||
override fun onRmsChanged(rmsdB: Float) {
|
||||
minRms = min(rmsdB, minRms)
|
||||
maxRms = max(rmsdB, maxRms)
|
||||
if (minRms != maxRms)
|
||||
icStt?.alpha = 0.5f + (rmsdB - minRms) / (2 * (maxRms - minRms))
|
||||
}
|
||||
|
||||
override fun onPartialResults(data: Bundle) {}
|
||||
|
||||
override fun onResults(data: Bundle) {
|
||||
stt = null
|
||||
data.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.let { results ->
|
||||
match?.apply {
|
||||
for (result in results) {
|
||||
Log.i("stt results", result)
|
||||
val soundex = soundex(result)
|
||||
for (player in players) {
|
||||
if (soundex == player.soundex) {
|
||||
icStt?.alpha = 0f
|
||||
unMuteAudio()
|
||||
updateScore(player)
|
||||
updateUI()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
showPopUp(getString(R.string.not_understood))
|
||||
startSTT()
|
||||
}
|
||||
|
||||
override fun onEndOfSpeech() {}
|
||||
|
||||
override fun onError(errorCode: Int) {
|
||||
muteAudio()
|
||||
Log.e(
|
||||
"stt", when (errorCode) {
|
||||
SpeechRecognizer.ERROR_AUDIO -> "Audio recording error"
|
||||
SpeechRecognizer.ERROR_CLIENT -> "Client side error"
|
||||
SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "Insufficient permissions"
|
||||
SpeechRecognizer.ERROR_NETWORK -> "Network error"
|
||||
SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "Network timeout"
|
||||
SpeechRecognizer.ERROR_NO_MATCH -> "No match"
|
||||
SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "RecognitionService busy"
|
||||
SpeechRecognizer.ERROR_SERVER -> "Error from server"
|
||||
SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "No speech input"
|
||||
else -> "Didn't understand, please try again."
|
||||
}
|
||||
)
|
||||
if (match?.matchStarted == true) startSTT()
|
||||
}
|
||||
|
||||
override fun onEvent(arg0: Int, arg1: Bundle?) {}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||
setContentView(R.layout.activity_match)
|
||||
|
||||
initMatchModel()
|
||||
findViews()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
fun initMatchModel() {
|
||||
matchModel = ViewModelProviders.of(this).get(MatchModel::class.java).apply {
|
||||
if (!matchStarted) {
|
||||
intent.apply {
|
||||
matchStarted = true
|
||||
val player1Name = getStringExtra("player1Name")
|
||||
val player2Name = getStringExtra("player2Name")
|
||||
players = listOf(
|
||||
Player(player1Name, 0),
|
||||
Player(player2Name, 0)
|
||||
)
|
||||
serviceSide = getIntExtra("starterId", 0)
|
||||
relaunchSide = when(serviceSide) {
|
||||
0 -> 1
|
||||
else -> 0
|
||||
}
|
||||
ttsEnabled = getBooleanExtra("enableTTS", false)
|
||||
sttEnabled = getBooleanExtra("enableSTT", false)
|
||||
saveState()
|
||||
|
||||
if (ttsEnabled) {
|
||||
tts = TextToSpeech(this@MatchActivity, WaitForTtsInit())
|
||||
if (sttEnabled) tts?.setOnUtteranceProgressListener(SttAfterTts())
|
||||
}
|
||||
if (!sttEnabled) showPopUp(getString(R.string.button_hint))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun findViews() {
|
||||
textScore = findViewById(R.id.textScore)
|
||||
textService = findViewById(R.id.textService)
|
||||
buttons = arrayOf(
|
||||
@ -90,10 +135,70 @@ class MatchActivity : AppCompatActivity() {
|
||||
findViewById(R.id.imgService0),
|
||||
findViewById(R.id.imgService1)
|
||||
)
|
||||
icStt = findViewById(R.id.icStt)
|
||||
|
||||
match = ViewModelProvider(this).get(MatchModel::class.java).apply {
|
||||
if (!matchStarted) {
|
||||
intent.apply {
|
||||
matchStarted = true
|
||||
val player1Name = getStringExtra("player1Name")
|
||||
val player2Name = getStringExtra("player2Name")
|
||||
players = listOf(
|
||||
Player(player1Name ?: getString(R.string.player_1_default_name), 0),
|
||||
Player(player2Name ?: getString(R.string.player_2_default_name), 0)
|
||||
)
|
||||
players.forEach {
|
||||
it.soundex = soundex(getString(R.string.soundex, it.name))
|
||||
}
|
||||
serviceSide = getIntExtra("starterId", 0)
|
||||
relaunchSide = when (serviceSide) {
|
||||
0 -> 1
|
||||
else -> 0
|
||||
}
|
||||
ttsEnabled = getBooleanExtra("enableTTS", false)
|
||||
sttEnabled = getBooleanExtra("enableSTT", false)
|
||||
saveState()
|
||||
|
||||
if (sttEnabled) {
|
||||
showPopUp(
|
||||
getString(
|
||||
R.string.STT_hint,
|
||||
players[0].name,
|
||||
players[1].name
|
||||
),
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
} else {
|
||||
showPopUp(getString(R.string.button_hint))
|
||||
}
|
||||
|
||||
if (ttsEnabled) {
|
||||
tts = TextToSpeech(this@MatchActivity, WaitForTtsInit()).apply {
|
||||
if (sttEnabled) setOnUtteranceProgressListener(WaitForTtsSpeak())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
stopSTT()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
stopSTT()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
fun updateUI() {
|
||||
matchModel?.apply {
|
||||
match?.apply {
|
||||
textScore?.text = getString(
|
||||
R.string.score_score,
|
||||
players[serviceSide].score,
|
||||
@ -105,40 +210,44 @@ class MatchActivity : AppCompatActivity() {
|
||||
button.text = fromHtml(getString(R.string.button_text, player.name, player.score))
|
||||
|
||||
imageViews[0].setImageResource(
|
||||
when(serviceSide) {
|
||||
when (serviceSide) {
|
||||
0 -> R.drawable.ic_service_0
|
||||
else -> 0
|
||||
}
|
||||
)
|
||||
imageViews[1].setImageResource(
|
||||
when(serviceSide) {
|
||||
when (serviceSide) {
|
||||
0 -> 0
|
||||
else -> R.drawable.ic_service_1
|
||||
}
|
||||
)
|
||||
|
||||
if (matchFinished)
|
||||
proclaimVictory()
|
||||
else {
|
||||
if (ttsEnabled) {
|
||||
var scoreSpeech: String = getString(
|
||||
R.string.update_score_speech,
|
||||
players[serviceSide].score,
|
||||
players[relaunchSide].score,
|
||||
players[serviceSide].name
|
||||
)
|
||||
if (matchPoint) scoreSpeech += getString(R.string.match_point)
|
||||
say(scoreSpeech)
|
||||
}
|
||||
if (matchStarted) {
|
||||
if (matchFinished)
|
||||
proclaimVictory()
|
||||
else {
|
||||
if (sttEnabled) SttDialog().show(supportFragmentManager, "SttDialog")
|
||||
if (ttsEnabled) {
|
||||
unMuteAudio()
|
||||
var scoreSpeech = getString(
|
||||
R.string.update_score_speech,
|
||||
players[serviceSide].score,
|
||||
players[relaunchSide].score,
|
||||
players[serviceSide].name
|
||||
)
|
||||
if (matchPoint) scoreSpeech += getString(R.string.match_point)
|
||||
say(scoreSpeech)
|
||||
} else if (sttEnabled) {
|
||||
startSTT()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun proclaimVictory() {
|
||||
matchModel?.apply {
|
||||
match?.apply {
|
||||
matchStarted = false
|
||||
stopSTT()
|
||||
val (loser, winner) = players.sortedBy { it.score }
|
||||
if (ttsEnabled) {
|
||||
say(
|
||||
@ -163,9 +272,9 @@ class MatchActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
fun updateScore(view: View) {
|
||||
matchModel?.apply {
|
||||
match?.apply {
|
||||
if (!matchFinished) {
|
||||
when(view) {
|
||||
when (view) {
|
||||
buttons[0] -> updateScore(players[0])
|
||||
buttons[1] -> updateScore(players[1])
|
||||
}
|
||||
@ -175,10 +284,10 @@ class MatchActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (matchModel?.pointId == 0)
|
||||
if (match?.pointId == 0)
|
||||
super.onBackPressed()
|
||||
else {
|
||||
matchModel?.undo()
|
||||
match?.undo()
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
@ -191,7 +300,7 @@ class MatchActivity : AppCompatActivity() {
|
||||
).show()
|
||||
}
|
||||
|
||||
fun showPopUp(textId: Int, duration: Int = Snackbar.LENGTH_SHORT) {
|
||||
fun showPopUp(textId: Int, duration: Int = Snackbar.LENGTH_INDEFINITE) {
|
||||
Snackbar.make(
|
||||
findViewById(R.id.coordinatorLayout),
|
||||
textId,
|
||||
@ -199,12 +308,87 @@ class MatchActivity : AppCompatActivity() {
|
||||
).show()
|
||||
}
|
||||
|
||||
fun stopSTT() {
|
||||
icStt?.alpha = 0f
|
||||
unMuteAudio()
|
||||
stt?.stopListening()
|
||||
stt?.destroy()
|
||||
stt = null
|
||||
}
|
||||
|
||||
fun startSTT() {
|
||||
stt?.stopListening()
|
||||
stt?.destroy()
|
||||
if (match?.matchStarted == true) {
|
||||
stt = SpeechRecognizer.createSpeechRecognizer(this@MatchActivity).apply {
|
||||
setRecognitionListener(SttListener())
|
||||
try {
|
||||
startListening(
|
||||
Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
|
||||
putExtra(
|
||||
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
|
||||
RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH
|
||||
)
|
||||
putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 10)
|
||||
putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
|
||||
if (!hasExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE)) {
|
||||
putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
match?.sttEnabled = false
|
||||
showPopUp(R.string.STT_unavailable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun say(text: String, queueMode: Int = TextToSpeech.QUEUE_FLUSH) {
|
||||
stopSTT()
|
||||
tts?.speak(
|
||||
text,
|
||||
queueMode,
|
||||
hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "TTS")
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun muteAudio() {
|
||||
(getSystemService(Context.AUDIO_SERVICE) as AudioManager).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_ALARM, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_RING, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_MUTE, 0)
|
||||
} else {
|
||||
setStreamMute(AudioManager.STREAM_NOTIFICATION, true)
|
||||
setStreamMute(AudioManager.STREAM_ALARM, true)
|
||||
setStreamMute(AudioManager.STREAM_MUSIC, true)
|
||||
setStreamMute(AudioManager.STREAM_RING, true)
|
||||
setStreamMute(AudioManager.STREAM_SYSTEM, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun unMuteAudio() {
|
||||
(getSystemService(Context.AUDIO_SERVICE) as AudioManager).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_ALARM, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_RING, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_UNMUTE, 0)
|
||||
} else {
|
||||
setStreamMute(AudioManager.STREAM_NOTIFICATION, false)
|
||||
setStreamMute(AudioManager.STREAM_ALARM, false)
|
||||
setStreamMute(AudioManager.STREAM_MUSIC, false)
|
||||
setStreamMute(AudioManager.STREAM_RING, false)
|
||||
setStreamMute(AudioManager.STREAM_SYSTEM, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package adrienmalin.pingpoints
|
||||
|
||||
import android.arch.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
|
||||
class MatchModel : ViewModel() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package adrienmalin.pingpoints
|
||||
|
||||
data class Player (
|
||||
data class Player(
|
||||
val name: String,
|
||||
var score: Int,
|
||||
val soundex: String = soundex(name)
|
||||
var soundex: String = ""
|
||||
)
|
||||
|
@ -9,14 +9,16 @@ import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.speech.SpeechRecognizer
|
||||
import android.speech.tts.TextToSpeech
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v4.app.ActivityCompat
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.RadioGroup
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||
|
||||
|
||||
class StarterNameActivity : AppCompatActivity() {
|
||||
@ -26,8 +28,8 @@ class StarterNameActivity : AppCompatActivity() {
|
||||
var player1NameInput: AutoCompleteTextView? = null
|
||||
var player2NameInput: AutoCompleteTextView? = null
|
||||
var starterRadioGroup: RadioGroup? = null
|
||||
var enableTtsSwitch: Switch? = null
|
||||
var enableSttSwitch: Switch? = null
|
||||
var enableTtsSwitch: SwitchMaterial? = null
|
||||
var enableSttSwitch: SwitchMaterial? = null
|
||||
var previousMatch: SharedPreferences? = null
|
||||
var previousPlayers: Set<String> = emptySet()
|
||||
|
||||
@ -53,10 +55,11 @@ class StarterNameActivity : AppCompatActivity() {
|
||||
fun restorePreviousSettings() {
|
||||
previousMatch = getPreferences(Context.MODE_PRIVATE).apply {
|
||||
getStringSet("previousPlayers", emptySet())?.let { previousPlayers = it.toSet() }
|
||||
val adapter = ArrayAdapter<String>(
|
||||
val adapter = ArrayAdapter(
|
||||
this@StarterNameActivity,
|
||||
android.R.layout.simple_list_item_1,
|
||||
previousPlayers.toList())
|
||||
previousPlayers.toList()
|
||||
)
|
||||
player1NameInput?.apply {
|
||||
setText(
|
||||
getString("previousPlayer2", getString(R.string.player_1_default_name)),
|
||||
@ -157,8 +160,7 @@ class StarterNameActivity : AppCompatActivity() {
|
||||
fun startMatch(view: View) {
|
||||
val player1Name = player1NameInput?.text.toString()
|
||||
val player2Name = player2NameInput?.text.toString()
|
||||
val radioStarterId = starterRadioGroup?.checkedRadioButtonId
|
||||
val starterId = when(radioStarterId) {
|
||||
val starterId = when (starterRadioGroup?.checkedRadioButtonId) {
|
||||
R.id.radioPlayer2Starts -> 1
|
||||
else -> 0
|
||||
}
|
||||
@ -166,14 +168,14 @@ class StarterNameActivity : AppCompatActivity() {
|
||||
val enableSTT = enableSttSwitch?.isChecked
|
||||
|
||||
// Save settings
|
||||
previousMatch?.edit()?.apply{
|
||||
player1Name.let { putString("previousPlayer1", it) }
|
||||
player2Name.let { putString("previousPlayer2", it) }
|
||||
previousMatch?.edit()?.apply {
|
||||
putString("previousPlayer1", player1Name)
|
||||
putString("previousPlayer2", player2Name)
|
||||
putInt("previousStarterId", starterId)
|
||||
putStringSet("previousPlayers", previousPlayers.plus(player1Name).plus(player2Name))
|
||||
enableTTS?.let { putBoolean("enableTTS", it) }
|
||||
enableSTT?.let { putBoolean("enableSTT", it) }
|
||||
commit()
|
||||
apply()
|
||||
}
|
||||
|
||||
startActivity(
|
||||
|
@ -1,200 +0,0 @@
|
||||
package adrienmalin.pingpoints
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.speech.RecognitionListener
|
||||
import android.speech.RecognizerIntent
|
||||
import android.speech.SpeechRecognizer
|
||||
import android.support.v4.app.DialogFragment
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
class SttDialog : DialogFragment() {
|
||||
var matchActivity: MatchActivity? = null
|
||||
var partialResultsTextView: TextView? = null
|
||||
var icStt: ImageView? = null
|
||||
var stt: SpeechRecognizer? = null
|
||||
var sttIntent: Intent? = null
|
||||
var pattern: Pattern? = null
|
||||
|
||||
inner class SttListener : RecognitionListener {
|
||||
val ERROR_NOT_UNDERSTOOD = 1
|
||||
var minRms: Float = 0f
|
||||
var maxRms: Float = 0f
|
||||
|
||||
override fun onReadyForSpeech(arg0: Bundle?) {}
|
||||
|
||||
override fun onBeginningOfSpeech() {}
|
||||
|
||||
override fun onBufferReceived(buffer: ByteArray?) {}
|
||||
|
||||
override fun onRmsChanged(rmsdB: Float) {
|
||||
minRms = min(rmsdB, minRms)
|
||||
maxRms = max(rmsdB, maxRms)
|
||||
if (minRms != maxRms)
|
||||
icStt?.alpha = 0.5f + (rmsdB - minRms) / (2 * (maxRms - minRms))
|
||||
}
|
||||
|
||||
override fun onPartialResults(data: Bundle) {
|
||||
data.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)?.let { results ->
|
||||
matchActivity?.apply {
|
||||
matchModel?.apply {
|
||||
for (result in results) {
|
||||
partialResultsTextView?.text = result
|
||||
pattern?.apply{
|
||||
val matcher = matcher(result)
|
||||
if (matcher.find()) {
|
||||
val foundName = matcher.group(1)
|
||||
for (player in players) {
|
||||
if (soundex(foundName) == player.soundex) {
|
||||
dismiss()
|
||||
updateScore(player)
|
||||
updateUI()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResults(data: Bundle) {
|
||||
partialResultsTextView?.text = getString(R.string.not_understood)
|
||||
onError(ERROR_NOT_UNDERSTOOD)
|
||||
}
|
||||
|
||||
override fun onEndOfSpeech() {}
|
||||
|
||||
override fun onError(errorCode: Int) {
|
||||
muteAudio()
|
||||
stt?.destroy()
|
||||
stt = SpeechRecognizer.createSpeechRecognizer(activity).apply {
|
||||
setRecognitionListener(this@SttListener)
|
||||
startListening(sttIntent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEvent(arg0: Int, arg1: Bundle?) {}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?) = AlertDialog.Builder(activity).apply {
|
||||
(context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater).inflate(R.layout.dialog_stt, null).let { view ->
|
||||
partialResultsTextView = view.findViewById(R.id.partialResultTextView)
|
||||
icStt = view.findViewById(R.id.icStt)
|
||||
|
||||
setView(view)
|
||||
|
||||
matchActivity = (activity as MatchActivity).apply {
|
||||
matchModel?.apply {
|
||||
view.findViewById<TextView>(R.id.sttHintTextView).text = getString(
|
||||
R.string.STT_hint,
|
||||
players[0].name,
|
||||
players[1].name
|
||||
)
|
||||
sttIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
|
||||
putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH)
|
||||
putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 10)
|
||||
putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
|
||||
putExtra(RecognizerIntent.EXTRA_PREFER_OFFLINE, true)
|
||||
putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, 30000)
|
||||
}
|
||||
stt = SpeechRecognizer.createSpeechRecognizer(activity).apply {
|
||||
setRecognitionListener(SttListener())
|
||||
try {
|
||||
stopListening()
|
||||
startListening(sttIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
sttEnabled = false
|
||||
dismiss()
|
||||
showPopUp(R.string.STT_unavailable)
|
||||
}
|
||||
}
|
||||
pattern = Pattern.compile(getString(R.string.pattern), Pattern.CASE_INSENSITIVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.create()!!
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
matchActivity?.apply {
|
||||
matchModel?.apply {
|
||||
stt?.destroy()
|
||||
stt = SpeechRecognizer.createSpeechRecognizer(activity).apply {
|
||||
setRecognitionListener(SttListener())
|
||||
try {
|
||||
stopListening()
|
||||
startListening(sttIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
sttEnabled = false
|
||||
dismiss()
|
||||
showPopUp(R.string.STT_unavailable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
unMuteAudio()
|
||||
stt?.stopListening()
|
||||
stt?.destroy()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun muteAudio() {
|
||||
activity?.apply {
|
||||
(getSystemService(Context.AUDIO_SERVICE) as AudioManager).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_ALARM, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_RING, AudioManager.ADJUST_MUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_MUTE, 0)
|
||||
} else {
|
||||
setStreamMute(AudioManager.STREAM_NOTIFICATION, true)
|
||||
setStreamMute(AudioManager.STREAM_ALARM, true)
|
||||
setStreamMute(AudioManager.STREAM_MUSIC, true)
|
||||
setStreamMute(AudioManager.STREAM_RING, true)
|
||||
setStreamMute(AudioManager.STREAM_SYSTEM, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun unMuteAudio() {
|
||||
activity?.apply {
|
||||
(getSystemService(Context.AUDIO_SERVICE) as AudioManager).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_ALARM, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_RING, AudioManager.ADJUST_UNMUTE, 0)
|
||||
adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_UNMUTE, 0)
|
||||
} else {
|
||||
setStreamMute(AudioManager.STREAM_NOTIFICATION, false)
|
||||
setStreamMute(AudioManager.STREAM_ALARM, false)
|
||||
setStreamMute(AudioManager.STREAM_MUSIC, false)
|
||||
setStreamMute(AudioManager.STREAM_RING, false)
|
||||
setStreamMute(AudioManager.STREAM_SYSTEM, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
package adrienmalin.pingpoints
|
||||
|
||||
import android.arch.lifecycle.ViewModelProviders
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.app.AppCompatDelegate
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.GridView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@ -31,17 +31,19 @@ class VictoryActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
fun initVictoryModel() {
|
||||
victoryModel = ViewModelProviders.of(this).get(VictoryModel::class.java).apply {
|
||||
victoryModel = ViewModelProvider(this).get(VictoryModel::class.java).apply {
|
||||
if (!matchFinished) {
|
||||
matchFinished = true
|
||||
winnerName = intent.getStringExtra("winnerName")
|
||||
winnerName = intent.getStringExtra("winnerName") ?: ""
|
||||
players = listOf(
|
||||
Player(
|
||||
intent.getStringExtra("player1Name"),
|
||||
intent.getStringExtra("player1Name")
|
||||
?: getString(R.string.player_1_default_name),
|
||||
intent.getIntExtra("player1Score", 0)
|
||||
),
|
||||
Player(
|
||||
intent.getStringExtra("player2Name"),
|
||||
intent.getStringExtra("player2Name")
|
||||
?: getString(R.string.player_2_default_name),
|
||||
intent.getIntExtra("player2Score", 0)
|
||||
)
|
||||
)
|
||||
@ -60,17 +62,17 @@ class VictoryActivity : AppCompatActivity() {
|
||||
players[1].score
|
||||
)
|
||||
findViewById<TextView>(R.id.player2NameTextView).text = players[1].name
|
||||
findViewById<GridView>(R.id.previousMatchesGrid).adapter = ArrayAdapter<String>(
|
||||
findViewById<GridView>(R.id.previousMatchesGrid).adapter = ArrayAdapter(
|
||||
this@VictoryActivity,
|
||||
R.layout.grid_item,
|
||||
R.id.grid_item_text,
|
||||
previousMatches.split("\t|\n".toRegex()).toMutableList()
|
||||
previousMatches.split("[\t\n]".toRegex()).toMutableList()
|
||||
)
|
||||
}
|
||||
|
||||
// Set HTML text for icons credits
|
||||
findViewById<TextView>(R.id.iconsCredit).apply {
|
||||
setText(fromHtml(getString(R.string.iconCredits)))
|
||||
text = fromHtml(getString(R.string.iconCredits))
|
||||
movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
}
|
||||
@ -88,19 +90,19 @@ class VictoryActivity : AppCompatActivity() {
|
||||
previousMatches
|
||||
)
|
||||
)
|
||||
commit()
|
||||
apply()
|
||||
}
|
||||
}
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
fun newMatch(view: View) {
|
||||
fun newMatch(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
startActivity(
|
||||
Intent(this, StarterNameActivity::class.java)
|
||||
)
|
||||
}
|
||||
|
||||
fun share(view: View) {
|
||||
fun share(@Suppress("UNUSED_PARAMETER") view: View) {
|
||||
victoryModel?.apply {
|
||||
startActivity(
|
||||
Intent().apply {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package adrienmalin.pingpoints
|
||||
|
||||
import android.arch.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class VictoryModel : ViewModel() {
|
||||
var matchFinished: Boolean = false
|
||||
|
@ -1,6 +1,7 @@
|
||||
package adrienmalin.pingpoints
|
||||
|
||||
import java.util.regex.*
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
val yNotPrecededByA:Pattern = Pattern.compile("(?<!A)Y")
|
||||
val hNotPrecededByCS: Pattern = Pattern.compile("(?<![CS])H")
|
||||
@ -12,7 +13,7 @@ val doubleLetter = Pattern.compile("(\\w)\\1+(?!\\1)")
|
||||
fun soundex(string: String): String {
|
||||
var s = string
|
||||
.trim()
|
||||
.toUpperCase()
|
||||
.toUpperCase(Locale.ROOT)
|
||||
.replace('Â', 'A')
|
||||
.replace('Ä', 'A')
|
||||
.replace('À', 'A')
|
||||
|
Reference in New Issue
Block a user