diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
index 41ba9fb..452d579 100644
Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ
diff --git a/app/build.gradle b/app/build.gradle
index 167350b..6005423 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -24,10 +24,14 @@ android {
}
dependencies {
+ def lifecycle_version = "2.0.0"
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ implementation 'com.android.support:design:28.0.0'
+ implementation "androidx.lifecycle:lifecycle-extensions-ktx:$lifecycle_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a3a6e85..7a4b14a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,26 +1,31 @@
+ package="adrienmalin.pingpoints">
+
-
-
-
-
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/adrienmalin/pingpoints/MatchActivity.kt b/app/src/main/java/adrienmalin/pingpoints/MatchActivity.kt
new file mode 100644
index 0000000..b0812aa
--- /dev/null
+++ b/app/src/main/java/adrienmalin/pingpoints/MatchActivity.kt
@@ -0,0 +1,24 @@
+package adrienmalin.pingpoints
+
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.app.AppCompatDelegate
+import android.view.View
+import android.arch.lifecycle.ViewModelProviders
+
+
+class MatchActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
+ setContentView(R.layout.activity_match)
+ setSupportActionBar(findViewById(R.id.toolbar))
+ val matchModel = ViewModelProviders.of(this).get(MatchModel::class.java)
+ }
+
+ fun updateScore(view: View) {
+
+ }
+
+}
diff --git a/app/src/main/java/adrienmalin/pingpoints/MatchModel.kt b/app/src/main/java/adrienmalin/pingpoints/MatchModel.kt
index 3672ffd..fa844ad 100644
--- a/app/src/main/java/adrienmalin/pingpoints/MatchModel.kt
+++ b/app/src/main/java/adrienmalin/pingpoints/MatchModel.kt
@@ -3,8 +3,15 @@ package adrienmalin.pingpoints
import android.arch.lifecycle.ViewModel
class MatchModel : ViewModel() {
- var players: List = listOf(Player(), Player())
- var server: Int = 0
- var ttsEnabled: Boolean = false
- var sttEnabled: Boolean = false
+ lateinit var players: List
+ lateinit var server: Int
+ lateinit var ttsEnabled: Boolean
+ lateinit var sttEnabled: Boolean
+
+ fun startMatch(player1Name: String, player2Name:String, starterId: Int, enableTTS: Boolean, enableSTT: Boolean) {
+ players = listOf(Player(player1Name), Player(player2Name))
+ server = starterId
+ ttsEnabled = enableTTS
+ sttEnabled = enableSTT
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/adrienmalin/pingpoints/StarterNameActivity.kt b/app/src/main/java/adrienmalin/pingpoints/StarterNameActivity.kt
index c3d30b4..433022b 100644
--- a/app/src/main/java/adrienmalin/pingpoints/StarterNameActivity.kt
+++ b/app/src/main/java/adrienmalin/pingpoints/StarterNameActivity.kt
@@ -1,19 +1,26 @@
package adrienmalin.pingpoints
+import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
+import android.content.Intent
import android.content.SharedPreferences
-import android.support.v7.app.AppCompatActivity
+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.text.method.LinkMovementMethod
import android.view.View
import android.widget.*
-import android.speech.tts.TextToSpeech
-import android.content.Intent
-import android.speech.SpeechRecognizer
-val CHECK_TTS = 1
+const val CHECK_TTS = 1
+const val ASK_PERMISSIONS_RECORD_AUDIO = 2
class StarterNameActivity : AppCompatActivity() {
@@ -29,23 +36,21 @@ class StarterNameActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_starter_name)
-
+ setSupportActionBar(findViewById(R.id.toolbar))
// Set HTML text for icons credits
findViewById(R.id.iconsCredit).run {
setHtmlText(getString(R.string.iconCredits))
movementMethod = LinkMovementMethod.getInstance()
}
-
// Find views
player1NameInput = findViewById(R.id.player1Name)
player2NameInput = findViewById(R.id.player2Name)
starterRadioGroup = findViewById(R.id.starterRadioGroup)
enableTtsSwitch = findViewById(R.id.enableTtsSwitch)
enableSttSwitch = findViewById(R.id.enableSttSwitch)
-
+ // Check if function is available on switch checked or swapped
enableTtsSwitch?.setOnCheckedChangeListener { view, isChecked -> checkTTS() }
enableTtsSwitch?.setOnTouchListener { view, event -> checkTTS(); false}
-
enableSttSwitch?.setOnCheckedChangeListener { view, isChecked -> checkSTT() }
enableSttSwitch?.setOnTouchListener { view, event -> checkSTT(); false}
@@ -94,15 +99,18 @@ class StarterNameActivity : AppCompatActivity() {
when (requestCode) {
CHECK_TTS -> {
if (resultCode != TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
- Toast.makeText(applicationContext, R.string.TTS_unavailable, Toast.LENGTH_LONG).show()
+ Snackbar.make(
+ findViewById(R.id.coordinatorLayout),
+ R.string.TTS_unavailable,
+ Snackbar.LENGTH_SHORT
+ ).show()
enableTtsSwitch?.isChecked = false
Intent().run {
action = TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
startActivity(this)
}
}
- }
- else -> {
+ } else -> {
}
}
}
@@ -111,28 +119,93 @@ class StarterNameActivity : AppCompatActivity() {
enableSttSwitch?.let {
if (it.isChecked) {
if (!SpeechRecognizer.isRecognitionAvailable(this)) {
- Toast.makeText(applicationContext, R.string.STT_unavailable, Toast.LENGTH_LONG).show()
- it.isChecked = false
+ Snackbar.make(
+ findViewById(R.id.coordinatorLayout),
+ R.string.STT_unavailable,
+ Snackbar.LENGTH_SHORT
+ ).show()
+ enableSttSwitch?.isChecked = false
+ } else {
+ // Ask for record audio permission
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
+ // Permission is not granted
+ // Should we show an explanation?
+ if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
+ AlertDialog.Builder(this)
+ .setTitle(R.string.STT)
+ .setMessage(R.string.explain_record_audio_request)
+ .setPositiveButton(R.string.OK) { dialog, id ->
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), ASK_PERMISSIONS_RECORD_AUDIO)
+ }
+ .setNegativeButton(R.string.cancel) { dialog, id ->
+ enableSttSwitch?.isChecked = false
+ }
+ .create()
+ .show()
+ } else {
+ // No explanation needed, we can request the permission.
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), ASK_PERMISSIONS_RECORD_AUDIO)
+ }
+ }
}
}
}
}
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ when (requestCode) {
+ ASK_PERMISSIONS_RECORD_AUDIO -> {
+ // If request is cancelled, the result arrays are empty.
+ if ((grantResults.isNotEmpty() && grantResults[0] != PackageManager.PERMISSION_GRANTED)) {
+ // permission denied
+ Snackbar.make(
+ findViewById(R.id.coordinatorLayout),
+ R.string.audio_record_permission_denied,
+ Snackbar.LENGTH_LONG
+ ).show()
+ enableSttSwitch?.isChecked = false
+ }
+ return
+ } else -> {
+ }
+ }
+ }
+
fun startMatch(view: View) {
val player1Name = player1NameInput?.text.toString()
val player2Name = player2NameInput?.text.toString()
+ val radioStarterId = starterRadioGroup?.checkedRadioButtonId
+ val enableTTS = enableTtsSwitch?.isChecked
+ val enableSTT = enableSttSwitch?.isChecked
// Save
- previousMatch?.edit()?.run{
- putString("previousPlayer1", player1Name)
- putString("previousPlayer2", player2Name)
- starterRadioGroup?.let{ putInt("previousStarterId", it.checkedRadioButtonId) }
- previousPlayers?.let { putStringSet("previousPlayers", it.plus(player1Name).plus(player2Name)) }
- enableTtsSwitch?.let { putBoolean("enableTTS", it.isChecked) }
- enableSttSwitch?.let { putBoolean("enableSTT", it.isChecked) }
+ previousMatch?.edit()?.apply{
+ player1Name.let { putString("previousPlayer1", it) }
+ player2Name.let { putString("previousPlayer2", it) }
+ radioStarterId?.let{ putInt("previousStarterId", it) }
+ putStringSet("previousPlayers", previousPlayers.plus(player1Name).plus(player2Name))
+ enableTTS?.let { putBoolean("enableTTS", it) }
+ enableSTT?.let { putBoolean("enableSTT", it) }
commit()
}
+ startActivity(
+ Intent(this, MatchActivity::class.java).apply {
+ putExtra("player1Name", player1Name)
+ putExtra("player2Name", player2Name)
+ putExtra(
+ "starterId",
+ when(radioStarterId) {
+ R.id.radioPlayer1Starts -> 0
+ R.id.radioPlayer2Starts -> 1
+ else -> 0
+ }
+ )
+ putExtra("enableTTS", enableTTS)
+ putExtra("enableSTT", enableSTT)
+ }
+ )
+
finish()
}
}
diff --git a/app/src/main/res/drawable/ic_left_service.xml b/app/src/main/res/drawable/ic_service_1.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_left_service.xml
rename to app/src/main/res/drawable/ic_service_1.xml
diff --git a/app/src/main/res/drawable/ic_right_service.xml b/app/src/main/res/drawable/ic_service_2.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_right_service.xml
rename to app/src/main/res/drawable/ic_service_2.xml
diff --git a/app/src/main/res/layout-land/activity_match.xml b/app/src/main/res/layout-land/activity_match.xml
new file mode 100644
index 0000000..1b2e76a
--- /dev/null
+++ b/app/src/main/res/layout-land/activity_match.xml
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout-land/activity_starter_name.xml b/app/src/main/res/layout-land/activity_starter_name.xml
index 83b6e76..b003586 100644
--- a/app/src/main/res/layout-land/activity_starter_name.xml
+++ b/app/src/main/res/layout-land/activity_starter_name.xml
@@ -1,103 +1,123 @@
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
\ No newline at end of file
+ android:layout_height="wrap_content"
+ android:text="@string/PingPointsCredits"
+ app:layout_constraintTop_toBottomOf="@+id/enableSttSwitch" app:layout_constraintStart_toStartOf="parent"
+ android:layout_marginLeft="8dp" android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent"
+ android:layout_marginEnd="8dp" android:layout_marginRight="8dp" android:layout_marginTop="24dp"/>
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_match.xml b/app/src/main/res/layout/activity_match.xml
new file mode 100644
index 0000000..7a61717
--- /dev/null
+++ b/app/src/main/res/layout/activity_match.xml
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_starter_name.xml b/app/src/main/res/layout/activity_starter_name.xml
index e5cc252..3316f83 100644
--- a/app/src/main/res/layout/activity_starter_name.xml
+++ b/app/src/main/res/layout/activity_starter_name.xml
@@ -1,5 +1,13 @@
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+ android:layout_height="wrap_content">
+
+
+
+
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 82ddfc8..74cea8a 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -12,4 +12,17 @@
<html>Icônes par <a href="http://www.freepik.com" title="Freepik">Freepik</a> chez <a href="https://www.flaticon.com/" title="Flaticon">flaticon.com</a> Licence <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></html>
Désolé, votre appareil ne permet pas la synthèse vocale.
Désolé, votre appareil ne permet pas la reconnaissance vocale.
+ "Cette appli utilise l'API de Google pour la reconnaissance vocale : votre voix sera enregistrée et envoyée aux serveurs de Google pour analyse.
+Cela requiert une connexion internet et la permission d'enregistrer des fichiers audio.
+Vous pouvez à tout moment changer la permission dans les paramètres Android."
+
+ OK
+ Annuler
+ La reconnaissance vocale a besoin de la permission d\'enregistrer des
+ fichiers audio pour fonctionner.
+
+ Service : %s
+ Score : %d - %d
+ Service
+ Ping Points
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index da003e7..2a4e3a1 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -2,5 +2,5 @@
#016df5
#004aa7
- #0088FF
+ #0088ff
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 19ad99c..d92b856 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -8,7 +8,25 @@
Let\'s go!
Swap names
Ping Points by Adrien Malin
- "<html>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></html>"
+ "<html>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a>
+ from <a href="https://www.flaticon.com/" title="Flaticon">flaticon.com</a> is
+ licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY
+ 3.0" target="_blank">CC 3.0 BY</a></html>"
+
Sorry, your device doesn\'t support text to speech.
Sorry, your device doesn\'t support voice recognition.
+ "This app uses Google API for voice recognition: your voice will be
+ recorded and analyzed by Google's servers.
+ It requires an internet connection and permission for audio recording.
+ You can always change permission in Android settings."
+
+ OK
+ Cancel
+ Audio recording permission required to use voice recognition.
+ Ping Points
+ Service: %s
+ Score: %d - %d
+ Service
+ %s <br /> <br /> <big> <big> %d </big> </big>
+