diff --git a/app/src/main/java/io/bartek/tts/WebService.kt b/app/src/main/java/io/bartek/tts/WebService.kt
index a8fef01..58fc3a1 100644
--- a/app/src/main/java/io/bartek/tts/WebService.kt
+++ b/app/src/main/java/io/bartek/tts/WebService.kt
@@ -15,29 +15,27 @@ import io.bartek.R
import io.bartek.web.TTSServer
class WebService : Service() {
+ private var port: Int = 8080
private var wakeLock: PowerManager.WakeLock? = null
private var isServiceStarted = false
private var ttsServer: TTSServer? = null
override fun onCreate() {
super.onCreate()
- Log.d("TTSService", "Service has been created")
startForeground(1, createNotification())
}
private fun createNotification(): Notification {
- val notificationChannelId = "HTTP SERVER CHANNEL"
-
// depending on the Android API that we're dealing with we will have
// to use a specific method to create the notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
val channel = NotificationChannel(
- notificationChannelId,
- "HTTP Server",
+ NOTIFICATION_CHANNEL_ID,
+ resources.getString(R.string.service_notification_category_name),
NotificationManager.IMPORTANCE_HIGH
).let {
- it.description = "HTTP Server channel with keeps the service running"
+ it.description = resources.getString(R.string.service_notification_category_description)
it.enableLights(true)
it.lightColor = Color.RED
it.enableVibration(true)
@@ -53,12 +51,12 @@ class WebService : Service() {
val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Notification.Builder(
this,
- notificationChannelId
+ NOTIFICATION_CHANNEL_ID
) else Notification.Builder(this)
return builder
- .setContentTitle("Endless Service")
- .setContentText("This is your favorite endless service working")
+ .setContentTitle(resources.getString(R.string.service_notification_title))
+ .setContentText(resources.getString(R.string.service_notification_text, port))
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker("Ticker text")
@@ -66,16 +64,15 @@ class WebService : Service() {
.build()
}
- override fun onBind(intent: Intent): IBinder? {
- Log.d("TTSService", "Something is willing to bind the service")
- return null
- }
+ override fun onBind(intent: Intent) = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- Log.d("TTSService", "onStartCommand with startId: $startId")
intent?.let {
when(it.action) {
- START -> startService(it.getIntExtra(PORT, 8080))
+ START -> {
+ port = it.getIntExtra(PORT, port)
+ startService()
+ }
STOP -> stopService()
}
}
@@ -87,13 +84,12 @@ class WebService : Service() {
ttsServer = null
}
- private fun startService(port: Int) {
+ private fun startService() {
if(isServiceStarted) return
- Log.d("TTSService", "Starting service...")
isServiceStarted = true
wakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
- newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "EndlessService::lock").apply {
+ newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WebService::lock").apply {
acquire()
}
}
@@ -101,7 +97,6 @@ class WebService : Service() {
}
private fun stopService() {
- Log.d("TTSService", "Stopping service...")
ttsServer?.stop()
ttsServer = null
wakeLock?.let {
@@ -115,6 +110,7 @@ class WebService : Service() {
}
companion object {
+ private const val NOTIFICATION_CHANNEL_ID = "TTSService.NOTIFICATION_CHANNEL"
const val PORT = "TTSService.PORT"
const val START = "START"
const val STOP = "STOP"
diff --git a/app/src/main/java/io/bartek/web/TTSServer.kt b/app/src/main/java/io/bartek/web/TTSServer.kt
index b585445..e246416 100644
--- a/app/src/main/java/io/bartek/web/TTSServer.kt
+++ b/app/src/main/java/io/bartek/web/TTSServer.kt
@@ -2,8 +2,13 @@ package io.bartek.web
import android.content.Context
import android.speech.tts.TextToSpeech
+import android.speech.tts.UtteranceProgressListener
+import android.util.Log
import android.widget.Toast
import fi.iki.elonen.NanoHTTPD
+import io.bartek.R
+import java.io.FileInputStream
+import java.io.InputStream
import java.util.*
class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port), TextToSpeech.OnInitListener {
@@ -11,20 +16,57 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port), Text
override fun serve(session: IHTTPSession?): Response {
tts.language = Locale("pl_PL")
- tts.speak(session?.uri, TextToSpeech.QUEUE_ADD, null, "")
+ val uuid = UUID.randomUUID().toString()
+ val file = createTempFile("tmp_tts_server", ".wav")
+ val lock = Object()
+ var error = false
+ tts.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
+ override fun onDone(utteranceId: String?) {
+ if(utteranceId == uuid) {
+ synchronized(lock) {
+ lock.notifyAll()
+ }
+ }
+ }
- return newFixedLengthResponse(""" { "message": "ok" } """)
+ override fun onError(utteranceId: String?) {
+ if(utteranceId == uuid) {
+ error = true
+ synchronized(lock) {
+ lock.notifyAll()
+ }
+ }
+ }
+
+ override fun onStart(utteranceId: String?) {}
+ })
+
+ synchronized(lock) {
+ tts.synthesizeToFile(session?.uri, null, file, uuid)
+ lock.wait()
+ }
+
+ val stream = FileInputStream(file)
+ val length = file.length()
+
+ Log.d("WAV", stream.toString())
+ Log.d("WAV", length.toString())
+
+ return when(error) {
+ false -> newFixedLengthResponse(Response.Status.OK, "audio/x-wav", stream, length)
+ else -> newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "TTS error on $uuid")
+ }
}
override fun onInit(status: Int) = start()
override fun start() {
super.start()
- Toast.makeText(context, "TTS-HTTP Server started", Toast.LENGTH_SHORT).show()
+ Toast.makeText(context, context.resources.getString(R.string.server_toast_service_started), Toast.LENGTH_SHORT).show()
}
override fun stop() {
super.stop()
- Toast.makeText(context, "TTS-HTTP Server stopped", Toast.LENGTH_SHORT).show()
+ Toast.makeText(context, context.resources.getString(R.string.server_toast_service_stopped), Toast.LENGTH_SHORT).show()
}
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 6891a8b..f2a2d4e 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -18,7 +18,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
- android:hint="Server port"
+ android:hint="@string/main_activity_server_port"
android:inputType="number"
android:text="8080" />
@@ -28,7 +28,7 @@
android:layout_height="wrap_content"
android:layout_weight="2"
android:onClick="startServer"
- android:text="Run" />
+ android:text="@string/main_activity_run" />
+ android:text="@string/main_activity_stop" />
@@ -44,5 +44,5 @@
android:id="@+id/ttsSettings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="TTS Settings" />
+ android:text="@string/main_activity_tts_settings" />
\ 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 2611049..ad73bc0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,15 @@
- TTSServer
+ TTS Server
+ HTTP Server
+ The fixed notification keeping the HTTP server alive
+ Server is running
+ The HTTP server is listening on port %1$d
+
+ TTS-HTTP Server started
+ TTS-HTTP Server stopped
+
+ Server port
+ Run
+ Stop
+ TTS Settings