Extract constants
This commit is contained in:
@@ -27,7 +27,9 @@ class MainActivity : AppCompatActivity() {
|
|||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
intent?.let {
|
intent?.let {
|
||||||
updateViewAccordingToServiceState(
|
updateViewAccordingToServiceState(
|
||||||
ServiceState.valueOf(it.getStringExtra("STATE") ?: "STOPPED")
|
ServiceState.valueOf(
|
||||||
|
it.getStringExtra(ForegroundService.STATE) ?: ServiceState.STOPPED.name
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,7 +41,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when(item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.open_preferences -> startActivity(Intent(this, PreferencesActivity::class.java))
|
R.id.open_preferences -> startActivity(Intent(this, PreferencesActivity::class.java))
|
||||||
R.id.open_help -> startActivity(Intent(this, HelpActivity::class.java))
|
R.id.open_help -> startActivity(Intent(this, HelpActivity::class.java))
|
||||||
}
|
}
|
||||||
@@ -72,7 +74,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
LocalBroadcastManager
|
LocalBroadcastManager
|
||||||
.getInstance(this)
|
.getInstance(this)
|
||||||
.registerReceiver(receiver, IntentFilter("io.bartek.web.server.CHANGE_STATE"))
|
.registerReceiver(receiver, IntentFilter(ForegroundService.CHANGE_STATE))
|
||||||
updateViewAccordingToServiceState(ForegroundService.state)
|
updateViewAccordingToServiceState(ForegroundService.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
app/src/main/java/io/bartek/preference/Preference.kt
Normal file
9
app/src/main/java/io/bartek/preference/Preference.kt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package io.bartek.preference
|
||||||
|
|
||||||
|
|
||||||
|
object PreferenceKey {
|
||||||
|
const val PORT = "preference_port"
|
||||||
|
const val ENABLE_SAY_ENDPOINT = "preference_enable_say_endpoint"
|
||||||
|
const val ENABLE_WAVE_ENDPOINT = "preference_enable_wave_endpoint"
|
||||||
|
const val TTS = "preference_tts"
|
||||||
|
}
|
||||||
@@ -24,7 +24,9 @@ class PreferencesFragment : PreferenceFragmentCompat() {
|
|||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
intent?.let {
|
intent?.let {
|
||||||
updateViewAccordingToServiceState(
|
updateViewAccordingToServiceState(
|
||||||
ServiceState.valueOf(it.getStringExtra("STATE") ?: "STOPPED")
|
ServiceState.valueOf(
|
||||||
|
it.getStringExtra(ForegroundService.STATE) ?: ServiceState.STOPPED.name
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +40,7 @@ class PreferencesFragment : PreferenceFragmentCompat() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
LocalBroadcastManager
|
LocalBroadcastManager
|
||||||
.getInstance(context!!)
|
.getInstance(context!!)
|
||||||
.registerReceiver(receiver, IntentFilter("io.bartek.web.server.CHANGE_STATE"))
|
.registerReceiver(receiver, IntentFilter(ForegroundService.CHANGE_STATE))
|
||||||
updateViewAccordingToServiceState(ForegroundService.state)
|
updateViewAccordingToServiceState(ForegroundService.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,15 +53,19 @@ class PreferencesFragment : PreferenceFragmentCompat() {
|
|||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.preferences, rootKey)
|
setPreferencesFromResource(R.xml.preferences, rootKey)
|
||||||
portPreference = findPreference("preference_port")!!
|
portPreference = findPreference(PreferenceKey.PORT)!!
|
||||||
portPreference.setOnBindEditTextListener { it.inputType = InputType.TYPE_CLASS_NUMBER }
|
portPreference.setOnBindEditTextListener { it.inputType = InputType.TYPE_CLASS_NUMBER }
|
||||||
sayEndpointPreference = findPreference("preference_enable_say_endpoint")!!
|
sayEndpointPreference = findPreference(PreferenceKey.ENABLE_SAY_ENDPOINT)!!
|
||||||
waveEndpointPreference = findPreference("preference_enable_wave_endpoint")!!
|
waveEndpointPreference = findPreference(PreferenceKey.ENABLE_WAVE_ENDPOINT)!!
|
||||||
ttsEnginePreference = findPreference("preference_tts")!!
|
ttsEnginePreference = findPreference(PreferenceKey.TTS)!!
|
||||||
ttsEnginePreference.setOnPreferenceClickListener {
|
ttsEnginePreference.setOnPreferenceClickListener {
|
||||||
startActivity(Intent("com.android.settings.TTS_SETTINGS"))
|
startActivity(Intent(ANDROID_TTS_SETTINGS))
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
updateViewAccordingToServiceState(ForegroundService.state)
|
updateViewAccordingToServiceState(ForegroundService.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ANDROID_TTS_SETTINGS = "com.android.settings.TTS_SETTINGS"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,15 +5,13 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Binder
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.IBinder
|
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import io.bartek.MainActivity
|
import io.bartek.MainActivity
|
||||||
import io.bartek.R
|
import io.bartek.R
|
||||||
|
import io.bartek.preference.PreferenceKey
|
||||||
import io.bartek.web.TTSServer
|
import io.bartek.web.TTSServer
|
||||||
import java.lang.Integer.parseInt
|
|
||||||
|
|
||||||
|
|
||||||
class ForegroundService : Service() {
|
class ForegroundService : Service() {
|
||||||
@@ -22,7 +20,7 @@ class ForegroundService : Service() {
|
|||||||
private var isServiceStarted = false
|
private var isServiceStarted = false
|
||||||
private var ttsServer: TTSServer? = null
|
private var ttsServer: TTSServer? = null
|
||||||
private val port: Int
|
private val port: Int
|
||||||
get() = preferences.getInt("preference_port", 8080)
|
get() = preferences.getInt(PreferenceKey.PORT, 8080)
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
@@ -91,7 +89,7 @@ class ForegroundService : Service() {
|
|||||||
isServiceStarted = true
|
isServiceStarted = true
|
||||||
wakeLock =
|
wakeLock =
|
||||||
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
|
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
|
||||||
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WebService::lock").apply {
|
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG).apply {
|
||||||
acquire()
|
acquire()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +117,9 @@ class ForegroundService : Service() {
|
|||||||
// than to place it as a static field
|
// than to place it as a static field
|
||||||
var state = ServiceState.STOPPED
|
var state = ServiceState.STOPPED
|
||||||
private const val NOTIFICATION_CHANNEL_ID = "TTSService.NOTIFICATION_CHANNEL"
|
private const val NOTIFICATION_CHANNEL_ID = "TTSService.NOTIFICATION_CHANNEL"
|
||||||
const val PORT = "TTSService.PORT"
|
private const val WAKELOCK_TAG = "ForegroundService::lock"
|
||||||
|
const val CHANGE_STATE = "io.bartek.service.CHANGE_STATE"
|
||||||
|
const val STATE = "STATE"
|
||||||
const val START = "START"
|
const val START = "START"
|
||||||
const val STOP = "STOP"
|
const val STOP = "STOP"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
|||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import fi.iki.elonen.NanoHTTPD
|
import fi.iki.elonen.NanoHTTPD
|
||||||
import fi.iki.elonen.NanoHTTPD.Response.Status.*
|
import fi.iki.elonen.NanoHTTPD.Response.Status.*
|
||||||
|
import io.bartek.preference.PreferenceKey
|
||||||
|
import io.bartek.service.ForegroundService
|
||||||
import io.bartek.service.ServiceState
|
import io.bartek.service.ServiceState
|
||||||
import io.bartek.tts.TTS
|
import io.bartek.tts.TTS
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@@ -23,7 +25,7 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port),
|
|||||||
override fun serve(session: IHTTPSession?): Response {
|
override fun serve(session: IHTTPSession?): Response {
|
||||||
try {
|
try {
|
||||||
session?.let {
|
session?.let {
|
||||||
return when(it.uri) {
|
return when (it.uri) {
|
||||||
"/wave" -> wave(it)
|
"/wave" -> wave(it)
|
||||||
"/say" -> say(it)
|
"/say" -> say(it)
|
||||||
else -> throw ResponseException(NOT_FOUND, "")
|
else -> throw ResponseException(NOT_FOUND, "")
|
||||||
@@ -39,7 +41,7 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port),
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun wave(session: IHTTPSession): Response {
|
private fun wave(session: IHTTPSession): Response {
|
||||||
if(!preferences.getBoolean("preference_enable_wave_endpoint", true)) {
|
if (!preferences.getBoolean(PreferenceKey.ENABLE_WAVE_ENDPOINT, true)) {
|
||||||
throw ResponseException(NOT_FOUND, "")
|
throw ResponseException(NOT_FOUND, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,17 +49,17 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port),
|
|||||||
throw ResponseException(METHOD_NOT_ALLOWED, "")
|
throw ResponseException(METHOD_NOT_ALLOWED, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.headers["content-type"]?.let { it != "application/json" } != false) {
|
if (session.headers[CONTENT_TYPE]?.let { it != MIME_JSON } != false) {
|
||||||
throw ResponseException(BAD_REQUEST, "")
|
throw ResponseException(BAD_REQUEST, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
val (text, language) = getRequestData(session)
|
val (text, language) = getRequestData(session)
|
||||||
val (stream, size) = tts.fetchTTSStream(text, language)
|
val (stream, size) = tts.fetchTTSStream(text, language)
|
||||||
return newFixedLengthResponse(OK, "audio/x-wav", stream, size)
|
return newFixedLengthResponse(OK, MIME_WAVE, stream, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun say(session: IHTTPSession): Response {
|
private fun say(session: IHTTPSession): Response {
|
||||||
if(!preferences.getBoolean("preference_enable_say_endpoint", true)) {
|
if (!preferences.getBoolean(PreferenceKey.ENABLE_SAY_ENDPOINT, true)) {
|
||||||
throw ResponseException(NOT_FOUND, "")
|
throw ResponseException(NOT_FOUND, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port),
|
|||||||
throw ResponseException(METHOD_NOT_ALLOWED, "")
|
throw ResponseException(METHOD_NOT_ALLOWED, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.headers["content-type"]?.let { it != "application/json" } != false) {
|
if (session.headers[CONTENT_TYPE]?.let { it != MIME_JSON } != false) {
|
||||||
throw ResponseException(BAD_REQUEST, "")
|
throw ResponseException(BAD_REQUEST, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +80,10 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port),
|
|||||||
val map = mutableMapOf<String, String>()
|
val map = mutableMapOf<String, String>()
|
||||||
session.parseBody(map)
|
session.parseBody(map)
|
||||||
val json = JSONObject(map["postData"] ?: "{}")
|
val json = JSONObject(map["postData"] ?: "{}")
|
||||||
val language = Locale(json.optString("language", "en_US"))
|
val language = json.optString("language")
|
||||||
|
.takeIf { it.isNotBlank() }
|
||||||
|
?.let { Locale(it) }
|
||||||
|
?: Locale.US
|
||||||
val text = json.optString("text") ?: throw ResponseException(BAD_REQUEST, "")
|
val text = json.optString("text") ?: throw ResponseException(BAD_REQUEST, "")
|
||||||
return TTSRequestData(text, language)
|
return TTSRequestData(text, language)
|
||||||
}
|
}
|
||||||
@@ -89,8 +94,8 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port),
|
|||||||
super.start()
|
super.start()
|
||||||
LocalBroadcastManager
|
LocalBroadcastManager
|
||||||
.getInstance(context)
|
.getInstance(context)
|
||||||
.sendBroadcast(Intent("io.bartek.web.server.CHANGE_STATE").also {
|
.sendBroadcast(Intent(ForegroundService.CHANGE_STATE).also {
|
||||||
it.putExtra("STATE", ServiceState.RUNNING.name)
|
it.putExtra(ForegroundService.STATE, ServiceState.RUNNING.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,8 +103,14 @@ class TTSServer(port: Int, private val context: Context) : NanoHTTPD(port),
|
|||||||
super.stop()
|
super.stop()
|
||||||
LocalBroadcastManager
|
LocalBroadcastManager
|
||||||
.getInstance(context)
|
.getInstance(context)
|
||||||
.sendBroadcast(Intent("io.bartek.web.server.CHANGE_STATE").also {
|
.sendBroadcast(Intent(ForegroundService.CHANGE_STATE).also {
|
||||||
it.putExtra("STATE", ServiceState.STOPPED.name)
|
it.putExtra(ForegroundService.STATE, ServiceState.STOPPED.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val MIME_JSON = "application/json"
|
||||||
|
private const val MIME_WAVE = "audio/x-wav"
|
||||||
|
private const val CONTENT_TYPE = "content-type"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user