Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc224e3e09 | ||
|
|
583ec62e39 | ||
|
|
bff0d29ee8 | ||
|
|
abb6f254bc |
@@ -11,8 +11,8 @@ android {
|
|||||||
applicationId = "ru.ua1zbe.svxremote"
|
applicationId = "ru.ua1zbe.svxremote"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 4
|
versionCode = 5
|
||||||
versionName = "1.0.2"
|
versionName = "1.0.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".SplashActivity"
|
android:name=".SplashActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/Theme.SvxRemote">
|
android:theme="@style/Theme.SvxRemote">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:configChanges="orientation|screenSize|keyboardHidden" />
|
android:configChanges="orientation|screenSize|keyboardHidden" />
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class MainActivity : Activity(), SvxService.Listener {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
SplashActivity.mainAlive = true
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
checkForUpdates()
|
checkForUpdates()
|
||||||
@@ -104,38 +105,18 @@ class MainActivity : Activity(), SvxService.Listener {
|
|||||||
startActivity(Intent(this, SettingsActivity::class.java))
|
startActivity(Intent(this, SettingsActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lblTg.setOnClickListener { showGroupsDialog() }
|
||||||
|
|
||||||
connectZone.setOnClickListener {
|
connectZone.setOnClickListener {
|
||||||
val s = svc
|
if (connected) {
|
||||||
if (connected && s != null) {
|
svc?.disconnect()
|
||||||
s.disconnect()
|
|
||||||
} else {
|
} else {
|
||||||
settings = Prefs.load(this)
|
|
||||||
if (settings.host.isBlank() || settings.callsign.isBlank()) {
|
if (settings.host.isBlank() || settings.callsign.isBlank()) {
|
||||||
toast(getString(R.string.toast_need_settings))
|
toast(getString(R.string.toast_need_settings))
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
if (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
requestPermissionsIfNeeded()
|
||||||
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), REQ_MIC)
|
connect()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,14 +147,28 @@ class MainActivity : Activity(), SvxService.Listener {
|
|||||||
refreshUi()
|
refreshUi()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var autoConnectAttempted = false
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
settings = Prefs.load(this)
|
settings = Prefs.load(this)
|
||||||
refreshUi()
|
refreshUi()
|
||||||
|
if (!autoConnectAttempted &&
|
||||||
|
settings.host.isNotBlank() &&
|
||||||
|
settings.callsign.isNotBlank()
|
||||||
|
) {
|
||||||
|
autoConnectAttempted = true
|
||||||
|
requestPermissionsIfNeeded()
|
||||||
|
connect()
|
||||||
|
}
|
||||||
|
if (pendingUpdate != null && updateDialog == null && canInstall()) {
|
||||||
|
startUpdate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
SplashActivity.mainAlive = false
|
||||||
svc?.listener = null
|
svc?.listener = null
|
||||||
unbindService(svcConn)
|
unbindService(svcConn)
|
||||||
}
|
}
|
||||||
@@ -309,6 +304,62 @@ class MainActivity : Activity(), SvxService.Listener {
|
|||||||
pttButton.enabled2 = connected
|
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() {
|
private fun checkForUpdates() {
|
||||||
Thread {
|
Thread {
|
||||||
val version = try {
|
val version = try {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ class SettingsActivity : Activity() {
|
|||||||
private lateinit var inputCallsign: EditText
|
private lateinit var inputCallsign: EditText
|
||||||
private lateinit var inputAuthKey: EditText
|
private lateinit var inputAuthKey: EditText
|
||||||
private lateinit var inputTg: EditText
|
private lateinit var inputTg: EditText
|
||||||
|
private lateinit var inputGroups: EditText
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -25,6 +26,7 @@ class SettingsActivity : Activity() {
|
|||||||
inputCallsign = findViewById(R.id.input_callsign)
|
inputCallsign = findViewById(R.id.input_callsign)
|
||||||
inputAuthKey = findViewById(R.id.input_auth_key)
|
inputAuthKey = findViewById(R.id.input_auth_key)
|
||||||
inputTg = findViewById(R.id.input_tg)
|
inputTg = findViewById(R.id.input_tg)
|
||||||
|
inputGroups = findViewById(R.id.input_groups)
|
||||||
|
|
||||||
val s = Prefs.load(this)
|
val s = Prefs.load(this)
|
||||||
inputHost.setText(s.host)
|
inputHost.setText(s.host)
|
||||||
@@ -32,6 +34,7 @@ class SettingsActivity : Activity() {
|
|||||||
inputCallsign.setText(s.callsign)
|
inputCallsign.setText(s.callsign)
|
||||||
inputAuthKey.setText(s.authKey)
|
inputAuthKey.setText(s.authKey)
|
||||||
inputTg.setText(s.talkGroup.toString())
|
inputTg.setText(s.talkGroup.toString())
|
||||||
|
inputGroups.setText(s.groups.joinToString(", "))
|
||||||
|
|
||||||
findViewById<Button>(R.id.btn_save).setOnClickListener {
|
findViewById<Button>(R.id.btn_save).setOnClickListener {
|
||||||
val host = inputHost.text.toString().trim()
|
val host = inputHost.text.toString().trim()
|
||||||
@@ -39,6 +42,10 @@ class SettingsActivity : Activity() {
|
|||||||
val callsign = inputCallsign.text.toString().trim()
|
val callsign = inputCallsign.text.toString().trim()
|
||||||
val authKey = inputAuthKey.text.toString()
|
val authKey = inputAuthKey.text.toString()
|
||||||
val tg = inputTg.text.toString().trim().toLongOrNull() ?: 11
|
val tg = inputTg.text.toString().trim().toLongOrNull() ?: 11
|
||||||
|
val groups = inputGroups.text.toString()
|
||||||
|
.split(',')
|
||||||
|
.mapNotNull { it.trim().toLongOrNull() }
|
||||||
|
.distinct()
|
||||||
|
|
||||||
if (host.isBlank() || callsign.isBlank()) {
|
if (host.isBlank() || callsign.isBlank()) {
|
||||||
toast(getString(R.string.toast_settings_empty))
|
toast(getString(R.string.toast_settings_empty))
|
||||||
@@ -52,7 +59,8 @@ class SettingsActivity : Activity() {
|
|||||||
port = port.coerceIn(1, 65535),
|
port = port.coerceIn(1, 65535),
|
||||||
callsign = callsign,
|
callsign = callsign,
|
||||||
authKey = authKey,
|
authKey = authKey,
|
||||||
talkGroup = tg.coerceAtLeast(0)
|
talkGroup = tg.coerceAtLeast(0),
|
||||||
|
groups = groups
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
toast(getString(R.string.saved))
|
toast(getString(R.string.saved))
|
||||||
|
|||||||
@@ -9,15 +9,23 @@ import android.view.animation.AccelerateDecelerateInterpolator
|
|||||||
/** Красивая заставка с плавным появлением логотипа. */
|
/** Красивая заставка с плавным появлением логотипа. */
|
||||||
class SplashActivity : Activity() {
|
class SplashActivity : Activity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
var mainAlive = false
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
if (mainAlive) {
|
||||||
|
openMain()
|
||||||
|
return
|
||||||
|
}
|
||||||
setContentView(R.layout.activity_splash)
|
setContentView(R.layout.activity_splash)
|
||||||
|
|
||||||
val title = findViewById<View>(R.id.splash_title)
|
val title = findViewById<View>(R.id.splash_title)
|
||||||
val subtitle = findViewById<View>(R.id.splash_subtitle)
|
val subtitle = findViewById<View>(R.id.splash_subtitle)
|
||||||
val line = findViewById<View>(R.id.splash_line)
|
val line = findViewById<View>(R.id.splash_line)
|
||||||
|
|
||||||
val baseAlpha = title.alpha
|
|
||||||
title.alpha = 0f
|
title.alpha = 0f
|
||||||
subtitle.alpha = 0f
|
subtitle.alpha = 0f
|
||||||
line.alpha = 0f
|
line.alpha = 0f
|
||||||
@@ -44,10 +52,19 @@ class SplashActivity : Activity() {
|
|||||||
.start()
|
.start()
|
||||||
|
|
||||||
window.decorView.postDelayed({
|
window.decorView.postDelayed({
|
||||||
val intent = Intent(this, MainActivity::class.java)
|
openMain()
|
||||||
startActivity(intent)
|
|
||||||
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
|
|
||||||
finish()
|
|
||||||
}, 4000)
|
}, 4000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun openMain() {
|
||||||
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
|
.addFlags(
|
||||||
|
Intent.FLAG_ACTIVITY_NEW_TASK or
|
||||||
|
Intent.FLAG_ACTIVITY_CLEAR_TOP or
|
||||||
|
Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||||
|
)
|
||||||
|
startActivity(intent)
|
||||||
|
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package ru.ua1zbe.svxremote
|
|||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
@@ -53,11 +54,22 @@ class SvxService : Service(), ReflectorClient.Callbacks {
|
|||||||
nm.createNotificationChannel(
|
nm.createNotificationChannel(
|
||||||
NotificationChannel("svx", "SVXRemote", NotificationManager.IMPORTANCE_LOW)
|
NotificationChannel("svx", "SVXRemote", NotificationManager.IMPORTANCE_LOW)
|
||||||
)
|
)
|
||||||
|
updateNotification(getString(R.string.notif_connected))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateNotification(text: String) {
|
||||||
|
val contentIntent = PendingIntent.getActivity(
|
||||||
|
this, 0,
|
||||||
|
Intent(this, MainActivity::class.java)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
val n = Notification.Builder(this, "svx")
|
val n = Notification.Builder(this, "svx")
|
||||||
.setContentTitle("SVXRemote")
|
.setContentTitle("SVXRemote")
|
||||||
.setContentText(getString(R.string.notif_connected))
|
.setContentText(text)
|
||||||
.setSmallIcon(android.R.drawable.ic_menu_call)
|
.setSmallIcon(R.drawable.ic_launcher_fg)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
|
.setContentIntent(contentIntent)
|
||||||
.build()
|
.build()
|
||||||
startForeground(1, n)
|
startForeground(1, n)
|
||||||
}
|
}
|
||||||
@@ -86,7 +98,10 @@ class SvxService : Service(), ReflectorClient.Callbacks {
|
|||||||
|
|
||||||
override fun onState(state: Int, detail: String?) {
|
override fun onState(state: Int, detail: String?) {
|
||||||
when (state) {
|
when (state) {
|
||||||
ReflectorClient.STATE_READY -> engine.startDecoder()
|
ReflectorClient.STATE_READY -> {
|
||||||
|
updateNotification(getString(R.string.notif_connected))
|
||||||
|
engine.startDecoder()
|
||||||
|
}
|
||||||
ReflectorClient.STATE_DISCONNECTED -> {
|
ReflectorClient.STATE_DISCONNECTED -> {
|
||||||
engine.stopDecoder()
|
engine.stopDecoder()
|
||||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||||
@@ -100,10 +115,12 @@ class SvxService : Service(), ReflectorClient.Callbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onTalkerStart(tg: Long, callsign: String) {
|
override fun onTalkerStart(tg: Long, callsign: String) {
|
||||||
|
updateNotification(getString(R.string.notif_talking, callsign))
|
||||||
listener?.onTalkerStart(tg, callsign)
|
listener?.onTalkerStart(tg, callsign)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTalkerStop(tg: Long, callsign: String) {
|
override fun onTalkerStop(tg: Long, callsign: String) {
|
||||||
|
updateNotification(getString(R.string.notif_last_talker, callsign))
|
||||||
listener?.onTalkerStop(tg, callsign)
|
listener?.onTalkerStop(tg, callsign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ data class ConnectionSettings(
|
|||||||
val port: Int,
|
val port: Int,
|
||||||
val callsign: String,
|
val callsign: String,
|
||||||
val authKey: String,
|
val authKey: String,
|
||||||
val talkGroup: Long
|
val talkGroup: Long,
|
||||||
|
val groups: List<Long> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
object Prefs {
|
object Prefs {
|
||||||
@@ -21,7 +22,12 @@ object Prefs {
|
|||||||
port = sp.getInt("port", 5300),
|
port = sp.getInt("port", 5300),
|
||||||
callsign = sp.getString("callsign", "") ?: "",
|
callsign = sp.getString("callsign", "") ?: "",
|
||||||
authKey = sp.getString("auth_key", "") ?: "",
|
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("callsign", s.callsign.trim())
|
||||||
.putString("auth_key", s.authKey)
|
.putString("auth_key", s.authKey)
|
||||||
.putLong("tg", s.talkGroup)
|
.putLong("tg", s.talkGroup)
|
||||||
|
.putString("groups", s.groups.distinct().joinToString(","))
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BIN
app/src/main/res/drawable-nodpi/ic_launcher_fg.png
Normal file
BIN
app/src/main/res/drawable-nodpi/ic_launcher_fg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<group
|
|
||||||
android:translateX="30"
|
|
||||||
android:translateY="30"
|
|
||||||
android:scaleX="1.5"
|
|
||||||
android:scaleY="1.5">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z" />
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
android:id="@+id/input_tg"
|
android:id="@+id/input_tg"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="24dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:textColor="@color/text_primary"
|
android:textColor="@color/text_primary"
|
||||||
android:textColorHint="@color/text_secondary"
|
android:textColorHint="@color/text_secondary"
|
||||||
@@ -119,6 +119,26 @@
|
|||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:hint="11" />
|
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
|
<Button
|
||||||
android:id="@+id/btn_save"
|
android:id="@+id/btn_save"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -9,8 +9,11 @@
|
|||||||
<string name="pref_callsign">Позывной</string>
|
<string name="pref_callsign">Позывной</string>
|
||||||
<string name="pref_auth_key">Пароль (AUTH_KEY)</string>
|
<string name="pref_auth_key">Пароль (AUTH_KEY)</string>
|
||||||
<string name="pref_tg">Группа вещания (TG)</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="btn_save">Сохранить</string>
|
||||||
<string name="app_version">SVXhomyak — v1.0.2</string>
|
<string name="app_version">SVXhomyak — v1.0.3</string>
|
||||||
<string name="saved">Сохранено</string>
|
<string name="saved">Сохранено</string>
|
||||||
<string name="pref_callsign_hint">например UA1ZBE</string>
|
<string name="pref_callsign_hint">например UA1ZBE</string>
|
||||||
|
|
||||||
@@ -26,7 +29,7 @@
|
|||||||
<string name="meter_mic">MIC</string>
|
<string name="meter_mic">MIC</string>
|
||||||
<string name="meter_idle">---</string>
|
<string name="meter_idle">---</string>
|
||||||
<string name="meter_db">-%1$d dB</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="talker_last_none">Последний: —</string>
|
||||||
<string name="status_connecting">Подключение…</string>
|
<string name="status_connecting">Подключение…</string>
|
||||||
<string name="status_connecting_ssl">Проверка ключа…</string>
|
<string name="status_connecting_ssl">Проверка ключа…</string>
|
||||||
@@ -34,6 +37,8 @@
|
|||||||
<string name="status_auth_failed">Ошибка авторизации</string>
|
<string name="status_auth_failed">Ошибка авторизации</string>
|
||||||
<string name="status_error">Ошибка: %1$s</string>
|
<string name="status_error">Ошибка: %1$s</string>
|
||||||
<string name="notif_connected">Соединение с рефлектором активно</string>
|
<string name="notif_connected">Соединение с рефлектором активно</string>
|
||||||
|
<string name="notif_talking">Говорит: %1$s</string>
|
||||||
|
<string name="notif_last_talker">Последний: %1$s</string>
|
||||||
|
|
||||||
<string name="btn_connect">Подключиться</string>
|
<string name="btn_connect">Подключиться</string>
|
||||||
<string name="btn_disconnect">Отключиться</string>
|
<string name="btn_disconnect">Отключиться</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user