Talk group switcher on main screen, auto-connect on launch
- Tapping the TG badge opens a group list; picking a group saves it and reconnects to the server with the new group - Groups configured in settings (comma-separated), defaults 9,11,12,13 - Auto-connect at app launch to the default group from settings
This commit is contained in:
@@ -105,38 +105,18 @@ class MainActivity : Activity(), SvxService.Listener {
|
||||
startActivity(Intent(this, SettingsActivity::class.java))
|
||||
}
|
||||
|
||||
lblTg.setOnClickListener { showGroupsDialog() }
|
||||
|
||||
connectZone.setOnClickListener {
|
||||
val s = svc
|
||||
if (connected && s != null) {
|
||||
s.disconnect()
|
||||
if (connected) {
|
||||
svc?.disconnect()
|
||||
} else {
|
||||
settings = Prefs.load(this)
|
||||
if (settings.host.isBlank() || settings.callsign.isBlank()) {
|
||||
toast(getString(R.string.toast_need_settings))
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), REQ_MIC)
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 33 &&
|
||||
checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), REQ_NOTIF)
|
||||
}
|
||||
startForegroundService(Intent(this, SvxService::class.java))
|
||||
bindService(Intent(this, SvxService::class.java), svcConn, Context.BIND_AUTO_CREATE)
|
||||
mainHandler.postDelayed({
|
||||
svc?.connect(
|
||||
ReflectorClient.Settings(
|
||||
host = settings.host,
|
||||
port = settings.port,
|
||||
callsign = settings.callsign,
|
||||
authKey = settings.authKey,
|
||||
talkGroup = settings.talkGroup
|
||||
)
|
||||
)
|
||||
}, 300)
|
||||
requestPermissionsIfNeeded()
|
||||
connect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,10 +147,23 @@ class MainActivity : Activity(), SvxService.Listener {
|
||||
refreshUi()
|
||||
}
|
||||
|
||||
private var autoConnectAttempted = false
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
settings = Prefs.load(this)
|
||||
refreshUi()
|
||||
if (!autoConnectAttempted &&
|
||||
settings.host.isNotBlank() &&
|
||||
settings.callsign.isNotBlank()
|
||||
) {
|
||||
autoConnectAttempted = true
|
||||
requestPermissionsIfNeeded()
|
||||
connect()
|
||||
}
|
||||
if (pendingUpdate != null && updateDialog == null && canInstall()) {
|
||||
startUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@@ -311,6 +304,62 @@ class MainActivity : Activity(), SvxService.Listener {
|
||||
pttButton.enabled2 = connected
|
||||
}
|
||||
|
||||
private fun requestPermissionsIfNeeded() {
|
||||
if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), REQ_MIC)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 33 &&
|
||||
checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), REQ_NOTIF)
|
||||
}
|
||||
}
|
||||
|
||||
/** Запустить сервис и подключиться с текущими настройками. */
|
||||
private fun connect() {
|
||||
startForegroundService(Intent(this, SvxService::class.java))
|
||||
bindService(Intent(this, SvxService::class.java), svcConn, Context.BIND_AUTO_CREATE)
|
||||
mainHandler.postDelayed({
|
||||
svc?.connect(
|
||||
ReflectorClient.Settings(
|
||||
host = settings.host,
|
||||
port = settings.port,
|
||||
callsign = settings.callsign,
|
||||
authKey = settings.authKey,
|
||||
talkGroup = settings.talkGroup
|
||||
)
|
||||
)
|
||||
}, 300)
|
||||
}
|
||||
|
||||
/** Переключиться на другую группу: пересохранить и переподключиться. */
|
||||
private fun switchGroup(tg: Long) {
|
||||
settings = settings.copy(talkGroup = tg)
|
||||
Prefs.save(this, settings)
|
||||
refreshUi()
|
||||
svc?.disconnect()
|
||||
mainHandler.postDelayed({ connect() }, 500)
|
||||
}
|
||||
|
||||
private fun showGroupsDialog() {
|
||||
val groups = (settings.groups + settings.talkGroup).distinct()
|
||||
if (groups.isEmpty()) {
|
||||
toast(getString(R.string.toast_groups_empty))
|
||||
return
|
||||
}
|
||||
val current = settings.talkGroup
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.select_tg)
|
||||
.setItems(groups.map { tg ->
|
||||
val label = getString(R.string.tg_badge, tg)
|
||||
if (tg == current) "$label ✓" else label
|
||||
}.toTypedArray()) { _, which ->
|
||||
val tg = groups[which]
|
||||
if (tg != current) switchGroup(tg)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun checkForUpdates() {
|
||||
Thread {
|
||||
val version = try {
|
||||
|
||||
@@ -15,6 +15,7 @@ class SettingsActivity : Activity() {
|
||||
private lateinit var inputCallsign: EditText
|
||||
private lateinit var inputAuthKey: EditText
|
||||
private lateinit var inputTg: EditText
|
||||
private lateinit var inputGroups: EditText
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -25,6 +26,7 @@ class SettingsActivity : Activity() {
|
||||
inputCallsign = findViewById(R.id.input_callsign)
|
||||
inputAuthKey = findViewById(R.id.input_auth_key)
|
||||
inputTg = findViewById(R.id.input_tg)
|
||||
inputGroups = findViewById(R.id.input_groups)
|
||||
|
||||
val s = Prefs.load(this)
|
||||
inputHost.setText(s.host)
|
||||
@@ -32,6 +34,7 @@ class SettingsActivity : Activity() {
|
||||
inputCallsign.setText(s.callsign)
|
||||
inputAuthKey.setText(s.authKey)
|
||||
inputTg.setText(s.talkGroup.toString())
|
||||
inputGroups.setText(s.groups.joinToString(", "))
|
||||
|
||||
findViewById<Button>(R.id.btn_save).setOnClickListener {
|
||||
val host = inputHost.text.toString().trim()
|
||||
@@ -39,6 +42,10 @@ class SettingsActivity : Activity() {
|
||||
val callsign = inputCallsign.text.toString().trim()
|
||||
val authKey = inputAuthKey.text.toString()
|
||||
val tg = inputTg.text.toString().trim().toLongOrNull() ?: 11
|
||||
val groups = inputGroups.text.toString()
|
||||
.split(',')
|
||||
.mapNotNull { it.trim().toLongOrNull() }
|
||||
.distinct()
|
||||
|
||||
if (host.isBlank() || callsign.isBlank()) {
|
||||
toast(getString(R.string.toast_settings_empty))
|
||||
@@ -52,7 +59,8 @@ class SettingsActivity : Activity() {
|
||||
port = port.coerceIn(1, 65535),
|
||||
callsign = callsign,
|
||||
authKey = authKey,
|
||||
talkGroup = tg.coerceAtLeast(0)
|
||||
talkGroup = tg.coerceAtLeast(0),
|
||||
groups = groups
|
||||
)
|
||||
)
|
||||
toast(getString(R.string.saved))
|
||||
|
||||
@@ -8,7 +8,8 @@ data class ConnectionSettings(
|
||||
val port: Int,
|
||||
val callsign: String,
|
||||
val authKey: String,
|
||||
val talkGroup: Long
|
||||
val talkGroup: Long,
|
||||
val groups: List<Long> = emptyList()
|
||||
)
|
||||
|
||||
object Prefs {
|
||||
@@ -21,7 +22,12 @@ object Prefs {
|
||||
port = sp.getInt("port", 5300),
|
||||
callsign = sp.getString("callsign", "") ?: "",
|
||||
authKey = sp.getString("auth_key", "") ?: "",
|
||||
talkGroup = sp.getLong("tg", 11)
|
||||
talkGroup = sp.getLong("tg", 11),
|
||||
groups = (sp.getString("groups", "") ?: "")
|
||||
.split(',')
|
||||
.mapNotNull { it.trim().toLongOrNull() }
|
||||
.distinct()
|
||||
.ifEmpty { listOf(9L, 11L, 12L, 13L) }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -33,6 +39,7 @@ object Prefs {
|
||||
.putString("callsign", s.callsign.trim())
|
||||
.putString("auth_key", s.authKey)
|
||||
.putLong("tg", s.talkGroup)
|
||||
.putString("groups", s.groups.distinct().joinToString(","))
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@
|
||||
android:id="@+id/input_tg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:inputType="number"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_secondary"
|
||||
@@ -119,6 +119,26 @@
|
||||
android:padding="12dp"
|
||||
android:hint="11" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pref_groups"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/input_groups"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:inputType="text"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textColorHint="@color/text_secondary"
|
||||
android:textSize="16sp"
|
||||
android:background="@drawable/bg_input"
|
||||
android:padding="12dp"
|
||||
android:hint="9, 11, 12, 13" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_save"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
<string name="pref_callsign">Позывной</string>
|
||||
<string name="pref_auth_key">Пароль (AUTH_KEY)</string>
|
||||
<string name="pref_tg">Группа вещания (TG)</string>
|
||||
<string name="pref_groups">Группы для переключения (через запятую)</string>
|
||||
<string name="select_tg">Выбор группы</string>
|
||||
<string name="toast_groups_empty">Добавьте группы в настройках</string>
|
||||
<string name="btn_save">Сохранить</string>
|
||||
<string name="app_version">SVXhomyak — v1.0.2</string>
|
||||
<string name="saved">Сохранено</string>
|
||||
@@ -26,7 +29,7 @@
|
||||
<string name="meter_mic">MIC</string>
|
||||
<string name="meter_idle">---</string>
|
||||
<string name="meter_db">-%1$d dB</string>
|
||||
<string name="tg_badge">TG%1$d</string>
|
||||
<string name="tg_badge">TG%1$d ▾</string>
|
||||
<string name="talker_last_none">Последний: —</string>
|
||||
<string name="status_connecting">Подключение…</string>
|
||||
<string name="status_connecting_ssl">Проверка ключа…</string>
|
||||
|
||||
Reference in New Issue
Block a user