Add additional info about server address to notification and main activity

This commit is contained in:
2020-05-19 17:58:35 +02:00
parent 6ae7b9632c
commit 51d0e698c7
9 changed files with 67 additions and 63 deletions

View File

@@ -1,7 +1,5 @@
package io.bartek.ttsserver.core.sonos.queue package io.bartek.ttsserver.core.sonos.queue
import android.content.SharedPreferences
import io.bartek.ttsserver.ui.preference.PreferenceKey
import io.bartek.ttsserver.core.sonos.worker.SonosWorker import io.bartek.ttsserver.core.sonos.worker.SonosWorker
import io.bartek.ttsserver.core.tts.engine.TTSEngine import io.bartek.ttsserver.core.tts.engine.TTSEngine
import io.bartek.ttsserver.core.util.NetworkUtil import io.bartek.ttsserver.core.util.NetworkUtil
@@ -9,28 +7,14 @@ import io.bartek.ttsserver.core.web.dto.SonosDTO
import java.util.concurrent.BlockingQueue import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.LinkedBlockingQueue
class SonosQueue( class SonosQueue(private val tts: TTSEngine, private val networkUtil: NetworkUtil) {
private val tts: TTSEngine,
private val networkUtil: NetworkUtil,
private val preferences: SharedPreferences
) {
private val queue: BlockingQueue<SonosDTO> = LinkedBlockingQueue() private val queue: BlockingQueue<SonosDTO> = LinkedBlockingQueue()
private var consumer: Thread? = null private var consumer: Thread? = null
private val host: String
get() = networkUtil.getIpAddress()
private val port: Int
get() = preferences.getInt(PreferenceKey.PORT, 8080)
fun run() { fun run() {
consumer?.interrupt() consumer?.interrupt()
consumer = Thread( consumer = Thread(SonosWorker(tts, networkUtil.serverAddress, queue))
SonosWorker( .also { it.name = "SonosQueue" }
tts,
host,
port,
queue
)
).also { it.name = "SonosQueue" }
consumer?.start() consumer?.start()
} }

View File

@@ -9,8 +9,7 @@ import java.util.concurrent.BlockingQueue
class SonosWorker( class SonosWorker(
private val tts: TTSEngine, private val tts: TTSEngine,
private val host: String, private val address: String,
private val port: Int,
private val queue: BlockingQueue<SonosDTO> private val queue: BlockingQueue<SonosDTO>
) : Runnable { ) : Runnable {
@@ -26,7 +25,7 @@ class SonosWorker(
SonosDiscovery.discover().firstOrNull { it.zoneGroupState.name == data.zone }?.let { SonosDiscovery.discover().firstOrNull { it.zoneGroupState.name == data.zone }?.let {
val file = tts.createTTSFile(data.text, data.language) val file = tts.createTTSFile(data.text, data.language)
val filename = file.name val filename = file.name
val url = "http://$host:$port/sonos/$filename" val url = "$address/sonos/$filename"
it.clip(url, data.volume, "") it.clip(url, data.volume, "")
} }
} }

View File

@@ -2,11 +2,16 @@ package io.bartek.ttsserver.core.util
import android.content.Context import android.content.Context
import android.content.Context.WIFI_SERVICE import android.content.Context.WIFI_SERVICE
import android.content.SharedPreferences
import android.net.wifi.WifiManager import android.net.wifi.WifiManager
import io.bartek.ttsserver.ui.preference.PreferenceKey
import java.net.InetAddress import java.net.InetAddress
class NetworkUtil(private val context: Context) { class NetworkUtil(private val context: Context, private val preferences: SharedPreferences) {
val serverAddress: String
get() = "http://${getIpAddress()}:${preferences.getInt(PreferenceKey.PORT, 8000)}"
fun getIpAddress(): String { fun getIpAddress(): String {
return (context.getApplicationContext().getSystemService(WIFI_SERVICE) as WifiManager).let { return (context.getApplicationContext().getSystemService(WIFI_SERVICE) as WifiManager).let {
inetAddress(it.dhcpInfo.ipAddress).toString().substring(1) inetAddress(it.dhcpInfo.ipAddress).toString().substring(1)

View File

@@ -6,12 +6,12 @@ import android.speech.tts.TextToSpeech
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import io.bartek.ttsserver.service.notification.ForegroundNotificationFactory
import io.bartek.ttsserver.core.sonos.queue.SonosQueue import io.bartek.ttsserver.core.sonos.queue.SonosQueue
import io.bartek.ttsserver.core.tts.engine.TTSEngine import io.bartek.ttsserver.core.tts.engine.TTSEngine
import io.bartek.ttsserver.core.tts.status.TTSStatusHolder import io.bartek.ttsserver.core.tts.status.TTSStatusHolder
import io.bartek.ttsserver.core.util.NetworkUtil import io.bartek.ttsserver.core.util.NetworkUtil
import io.bartek.ttsserver.core.web.server.WebServerFactory import io.bartek.ttsserver.core.web.server.WebServerFactory
import io.bartek.ttsserver.service.notification.ForegroundNotificationFactory
import javax.inject.Singleton import javax.inject.Singleton
@Module @Module
@@ -38,13 +38,12 @@ class TTSModule {
context: Context, context: Context,
tts: TTSEngine, tts: TTSEngine,
sonos: SonosQueue sonos: SonosQueue
) = ) = WebServerFactory(
WebServerFactory( preferences,
preferences, context,
context, tts,
tts, sonos
sonos )
)
@Provides @Provides
@Singleton @Singleton
@@ -52,17 +51,17 @@ class TTSModule {
@Provides @Provides
@Singleton @Singleton
fun networkUtil(context: Context) = NetworkUtil(context) fun networkUtil(context: Context, preferences: SharedPreferences) =
NetworkUtil(context, preferences)
@Provides @Provides
@Singleton @Singleton
fun sonosQueue(tts: TTSEngine, networkUtil: NetworkUtil, preferences: SharedPreferences) = fun sonosQueue(tts: TTSEngine, networkUtil: NetworkUtil) = SonosQueue(tts, networkUtil)
SonosQueue(tts, networkUtil, preferences)
@Provides @Provides
@Singleton @Singleton
fun foregroundNotificationFactory(context: Context) = fun foregroundNotificationFactory(
ForegroundNotificationFactory( context: Context,
context networkUtil: NetworkUtil
) ) = ForegroundNotificationFactory(context, networkUtil)
} }

View File

@@ -3,10 +3,8 @@ package io.bartek.ttsserver.service.foreground
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.os.PowerManager import android.os.PowerManager
import dagger.android.DaggerService import dagger.android.DaggerService
import io.bartek.ttsserver.ui.preference.PreferenceKey
import io.bartek.ttsserver.core.web.server.WebServer import io.bartek.ttsserver.core.web.server.WebServer
import io.bartek.ttsserver.core.web.server.WebServerFactory import io.bartek.ttsserver.core.web.server.WebServerFactory
import io.bartek.ttsserver.service.notification.ForegroundNotificationFactory import io.bartek.ttsserver.service.notification.ForegroundNotificationFactory
@@ -18,11 +16,6 @@ class ForegroundService : DaggerService() {
private var wakeLock: PowerManager.WakeLock? = null private var wakeLock: PowerManager.WakeLock? = null
private var isServiceStarted = false private var isServiceStarted = false
private var webServer: WebServer? = null private var webServer: WebServer? = null
private val port: Int
get() = preferences.getInt(PreferenceKey.PORT, 8080)
@Inject
lateinit var preferences: SharedPreferences
@Inject @Inject
lateinit var webServerFactory: WebServerFactory lateinit var webServerFactory: WebServerFactory
@@ -32,7 +25,7 @@ class ForegroundService : DaggerService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
startForeground(1, notificationFactory.createForegroundNotification(port)) startForeground(1, notificationFactory.createForegroundNotification())
} }
override fun onBind(intent: Intent) = null override fun onBind(intent: Intent) = null

View File

@@ -9,25 +9,32 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import io.bartek.R import io.bartek.R
import io.bartek.ttsserver.core.util.NetworkUtil
import io.bartek.ttsserver.ui.main.MainActivity import io.bartek.ttsserver.ui.main.MainActivity
class ForegroundNotificationFactory(private val context: Context) { class ForegroundNotificationFactory(
private val context: Context,
private val networkUtil: NetworkUtil
) {
private val oreo: Boolean private val oreo: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
fun createForegroundNotification(port: Int): Notification { private val notificationContent: String
get() = context.getString(R.string.service_notification_text, networkUtil.serverAddress)
fun createForegroundNotification(): Notification {
createNotificationChannel() createNotificationChannel()
return buildNotification(port, createPendingIntent()) return buildNotification(createPendingIntent())
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private fun buildNotification(port: Int, pendingIntent: PendingIntent?) = private fun buildNotification(pendingIntent: PendingIntent?) =
provideNotificationBuilder() provideNotificationBuilder()
.setContentTitle(context.resources.getString(R.string.service_notification_title)) .setContentTitle(context.resources.getString(R.string.service_notification_title))
.setContentText(context.resources.getString(R.string.service_notification_text, port)) .setContentText(notificationContent)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_foreground_service) .setSmallIcon(R.drawable.ic_foreground_service)
.setTicker(context.getString(R.string.service_notification_text, port)) .setTicker(notificationContent)
.setPriority(Notification.PRIORITY_HIGH) // for under android 26 compatibility .setPriority(Notification.PRIORITY_HIGH) // for under android 26 compatibility
.build() .build()
@@ -57,7 +64,8 @@ class ForegroundNotificationFactory(private val context: Context) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@SuppressLint("NewApi") @SuppressLint("NewApi")
private fun provideNotificationBuilder() = private fun provideNotificationBuilder() =
if (oreo) Notification.Builder(context, if (oreo) Notification.Builder(
context,
NOTIFICATION_CHANNEL_ID NOTIFICATION_CHANNEL_ID
) )
else Notification.Builder(context) else Notification.Builder(context)

View File

@@ -1,9 +1,6 @@
package io.bartek.ttsserver.ui.main package io.bartek.ttsserver.ui.main
import android.content.BroadcastReceiver import android.content.*
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
@@ -14,20 +11,28 @@ import androidx.appcompat.widget.AppCompatImageButton
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import dagger.android.support.DaggerAppCompatActivity import dagger.android.support.DaggerAppCompatActivity
import io.bartek.R import io.bartek.R
import io.bartek.ttsserver.ui.help.HelpActivity import io.bartek.ttsserver.core.util.NetworkUtil
import io.bartek.ttsserver.ui.preference.PreferencesActivity
import io.bartek.ttsserver.service.foreground.ForegroundService import io.bartek.ttsserver.service.foreground.ForegroundService
import io.bartek.ttsserver.service.state.ServiceState import io.bartek.ttsserver.service.state.ServiceState
import io.bartek.ttsserver.ui.help.HelpActivity
import io.bartek.ttsserver.ui.preference.PreferencesActivity
import javax.inject.Inject import javax.inject.Inject
class MainActivity : DaggerAppCompatActivity() { class MainActivity : DaggerAppCompatActivity() {
private lateinit var serverControlButton: AppCompatImageButton private lateinit var serverControlButton: AppCompatImageButton
private lateinit var serverStatus: TextView
private lateinit var promptText: TextView private lateinit var promptText: TextView
@Inject @Inject
lateinit var context: Context lateinit var context: Context
@Inject
lateinit var preferences: SharedPreferences
@Inject
lateinit var networkUtil: NetworkUtil
private val receiver = object : BroadcastReceiver() { private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
(intent?.getStringExtra(ForegroundService.STATE) ?: ServiceState.STOPPED.name) (intent?.getStringExtra(ForegroundService.STATE) ?: ServiceState.STOPPED.name)
@@ -55,10 +60,13 @@ class MainActivity : DaggerAppCompatActivity() {
when (newState) { when (newState) {
ServiceState.STOPPED -> { ServiceState.STOPPED -> {
serverControlButton.setImageResource(R.drawable.ic_power_off) serverControlButton.setImageResource(R.drawable.ic_power_off)
serverStatus.text = getString(R.string.main_activity_server_status_down)
promptText.text = getString(R.string.main_activity_prompt_to_run) promptText.text = getString(R.string.main_activity_prompt_to_run)
} }
ServiceState.RUNNING -> { ServiceState.RUNNING -> {
serverControlButton.setImageResource(R.drawable.ic_power_on) serverControlButton.setImageResource(R.drawable.ic_power_on)
serverStatus.text =
getString(R.string.main_activity_server_status_up, networkUtil.serverAddress)
promptText.text = getString(R.string.main_activity_prompt_to_stop) promptText.text = getString(R.string.main_activity_prompt_to_stop)
} }
} }
@@ -68,6 +76,7 @@ class MainActivity : DaggerAppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
serverControlButton = findViewById(R.id.server_control_button) serverControlButton = findViewById(R.id.server_control_button)
serverStatus = findViewById(R.id.server_status)
promptText = findViewById(R.id.prompt_text) promptText = findViewById(R.id.prompt_text)
} }

View File

@@ -8,10 +8,17 @@
tools:context=".ttsserver.ui.main.MainActivity"> tools:context=".ttsserver.ui.main.MainActivity">
<TextView <TextView
android:id="@+id/prompt_text" android:id="@+id/server_status"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:text="@string/main_activity_server_status_down"
android:textAlignment="center" />
<TextView
android:id="@+id/prompt_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/main_activity_prompt_to_run" android:text="@string/main_activity_prompt_to_run"
android:textAlignment="center" /> android:textAlignment="center" />

View File

@@ -4,15 +4,15 @@
<string name="permission_http_server_label">booting up TTS HTTP server</string> <string name="permission_http_server_label">booting up TTS HTTP server</string>
<string name="permission_http_server_description">Allows application to run HTTP server which provides a TTS services.</string> <string name="permission_http_server_description">Allows application to run HTTP server which provides a TTS services.</string>
<string name="main_activity_run">Run</string> <string name="main_activity_server_status_down">The server is down</string>
<string name="main_activity_stop">Stop</string> <string name="main_activity_server_status_up">The server is up: %1$s</string>
<string name="main_activity_prompt_to_run">Tap power on button to run the server</string> <string name="main_activity_prompt_to_run">Tap power on button to run the server</string>
<string name="main_activity_prompt_to_stop">Tap power off button to stop the server</string> <string name="main_activity_prompt_to_stop">Tap power off button to stop the server</string>
<string name="service_notification_category_name">HTTP Server</string> <string name="service_notification_category_name">HTTP Server</string>
<string name="service_notification_category_description">The fixed notification keeping the HTTP server alive</string> <string name="service_notification_category_description">The fixed notification keeping the HTTP server alive</string>
<string name="service_notification_title">Server is running</string> <string name="service_notification_title">Server is running</string>
<string name="service_notification_text">The HTTP server is listening on port %1$d</string> <string name="service_notification_text">The HTTP server is listening on address %1$s</string>
<string name="title_activity_preferences">Settings</string> <string name="title_activity_preferences">Settings</string>
<string name="preference_port_summary">The desired port on which HTTP server is intended to listening</string> <string name="preference_port_summary">The desired port on which HTTP server is intended to listening</string>