Compare commits

...
14 Commits
121 changed files with 1681 additions and 1086 deletions
+1
View File
@@ -1,3 +1,4 @@
.idea .idea
.gradle .gradle
build/ build/
/fastlane/report.xml
+3
View File
@@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "fastlane"
+218
View File
@@ -0,0 +1,218 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.5)
rexml
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.554.0)
aws-sdk-core (3.126.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.54.0)
aws-sdk-core (~> 3, >= 3.126.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.112.0)
aws-sdk-core (~> 3, >= 3.126.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.4.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
digest-crc (0.6.4)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.2.3)
excon (0.91.0)
faraday (1.9.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.3)
multipart-post (>= 1.2, < 3)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.204.3)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
naturally (~> 2.2)
optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.16.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-core (0.4.2)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
webrick
google-apis-iamcredentials_v1 (0.10.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-playcustomapp_v1 (0.7.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-storage_v1 (0.11.0)
google-apis-core (>= 0.4, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.5.0)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.2.0)
google-cloud-storage (1.36.1)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.1.0)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.4)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.5.0)
json (2.6.1)
jwt (2.3.0)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.1.2)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
naturally (2.2.1)
optparse (0.1.1)
os (1.1.4)
plist (3.6.0)
public_suffix (4.0.6)
rake (13.0.6)
representable (3.1.1)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rouge (2.0.7)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.3)
signet (0.16.0)
addressable (~> 2.8)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8)
unicode-display_width (1.8.0)
webrick (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.21.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
x86_64-linux
DEPENDENCIES
fastlane
BUNDLED WITH
2.2.8
+5 -1
View File
@@ -1,2 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="foss_upgrade_donate_label">Dona</string>
<string name="foss_upgrade_alreadydonated_label">Ho già donato</string>
<string name="foss_upgrade_no_money_label">Spendo tutti i miei soldi per gli AirPods</string>
</resources>
+5 -1
View File
@@ -1,2 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="foss_upgrade_donate_label">Doner</string>
<string name="foss_upgrade_alreadydonated_label">Jeg har allerede donert</string>
<string name="foss_upgrade_no_money_label">Jeg bruker alle pengene mine på AirPods</string>
</resources>
+5 -1
View File
@@ -1,2 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="foss_upgrade_donate_label">Bağış</string>
<string name="foss_upgrade_alreadydonated_label">Ben zaten bağışladım</string>
<string name="foss_upgrade_no_money_label">Tüm paramı AirPod\'lara harcıyorum</string>
</resources>
+4 -1
View File
@@ -1,2 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="upgrades_gplay_unavailable_error">I servizi di Google Play non sono disponibili.</string>
<string name="upgrades_no_purchases_found_check_account">Nessun acquisto trovato. Stai usando l\'account giusto?</string>
</resources>
+4 -1
View File
@@ -1,2 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="upgrades_gplay_unavailable_error">Google Play-tjenester er utilgjengelige.</string>
<string name="upgrades_no_purchases_found_check_account">Ingen kjøp funnet. Bruker du riktig konto?</string>
</resources>
+4 -1
View File
@@ -1,2 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="upgrades_gplay_unavailable_error">Google Play hizmetleri kullanılamıyor.</string>
<string name="upgrades_no_purchases_found_check_account">Satın alma bulunamadı. Doğru hesabı mı kullanıyorsunuz?</string>
</resources>
@@ -33,6 +33,7 @@ class BleScanner @Inject constructor(
scannerMode: ScannerMode, scannerMode: ScannerMode,
compatMode: Boolean, compatMode: Boolean,
): Flow<List<BleScanResult>> = callbackFlow { ): Flow<List<BleScanResult>> = callbackFlow {
log(TAG, VERBOSE) { "scan(filters=$filters, scannerMode=$scannerMode, compatMode=$compatMode)" }
if (compatMode) log(TAG, WARN) { "Using compatibilityMode!" } if (compatMode) log(TAG, WARN) { "Using compatibilityMode!" }
val adapter = bluetoothManager.adapter val adapter = bluetoothManager.adapter
@@ -75,6 +75,19 @@ class FakeBleData @Inject constructor(
fakeDevices.add(this) fakeDevices.add(this)
} }
} }
// Tws i99999
BleScanResult(
address = "5E:9E:D1:29:D2:6D",
rssi = Random.nextInt(15, 75) * -1,
generatedAtNanos = SystemClockWrap.elapsedRealtimeNanos + 400,
manufacturerSpecificData = mapOf(76 to "07 13 01 02 20 71 AA 37 32 00 10 00 64 64 FF 00 00 00 00 00 00".hexToByteArray())
).run {
if (Random.nextBoolean()) {
fakeDevices.add(this)
}
}
// Unknown Device // Unknown Device
BleScanResult( BleScanResult(
address = "6E:9E:D1:49:D2:6D", address = "6E:9E:D1:49:D2:6D",
@@ -14,9 +14,8 @@ import eu.darken.capod.common.lists.modular.mods.TypedVHCreatorMod
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
import eu.darken.capod.main.ui.overview.cards.pods.BasicSingleApplePodsCardVH import eu.darken.capod.main.ui.overview.cards.pods.DualPodsCardVH
import eu.darken.capod.main.ui.overview.cards.pods.DualApplePodsCardVH import eu.darken.capod.main.ui.overview.cards.pods.SinglePodsCardVH
import eu.darken.capod.main.ui.overview.cards.pods.SingleApplePodsCardVH
import eu.darken.capod.main.ui.overview.cards.pods.UnknownPodDeviceCardVH import eu.darken.capod.main.ui.overview.cards.pods.UnknownPodDeviceCardVH
import javax.inject.Inject import javax.inject.Inject
@@ -29,9 +28,8 @@ class OverviewAdapter @Inject constructor() :
init { init {
modules.add(DataBinderMod(data)) modules.add(DataBinderMod(data))
modules.add(TypedVHCreatorMod({ data[it] is PermissionCardVH.Item }) { PermissionCardVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is PermissionCardVH.Item }) { PermissionCardVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is DualApplePodsCardVH.Item }) { DualApplePodsCardVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is DualPodsCardVH.Item }) { DualPodsCardVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is SingleApplePodsCardVH.Item }) { SingleApplePodsCardVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is SinglePodsCardVH.Item }) { SinglePodsCardVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is BasicSingleApplePodsCardVH.Item }) { BasicSingleApplePodsCardVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is MissingMainDeviceVH.Item }) { MissingMainDeviceVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is MissingMainDeviceVH.Item }) { MissingMainDeviceVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is BluetoothDisabledVH.Item }) { BluetoothDisabledVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is BluetoothDisabledVH.Item }) { BluetoothDisabledVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is UnknownPodDeviceCardVH.Item }) { UnknownPodDeviceCardVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is UnknownPodDeviceCardVH.Item }) { UnknownPodDeviceCardVH(it) })
@@ -20,23 +20,23 @@ import eu.darken.capod.main.core.PermissionTool
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH import eu.darken.capod.main.ui.overview.cards.MissingMainDeviceVH
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
import eu.darken.capod.main.ui.overview.cards.pods.* import eu.darken.capod.main.ui.overview.cards.pods.DualPodsCardVH
import eu.darken.capod.main.ui.overview.cards.pods.SinglePodsCardVH
import eu.darken.capod.main.ui.overview.cards.pods.UnknownPodDeviceCardVH
import eu.darken.capod.monitor.core.PodMonitor import eu.darken.capod.monitor.core.PodMonitor
import eu.darken.capod.monitor.core.worker.MonitorControl import eu.darken.capod.monitor.core.worker.MonitorControl
import eu.darken.capod.pods.core.DualPodDevice
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.SinglePodDevice
import eu.darken.capod.pods.core.apple.DualApplePods
import eu.darken.capod.pods.core.apple.SingleApplePods
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import java.time.Instant import java.time.Instant
import java.util.*
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class OverviewFragmentVM @Inject constructor( class OverviewFragmentVM @Inject constructor(
handle: SavedStateHandle, @Suppress("UNUSED_PARAMETER") handle: SavedStateHandle,
dispatcherProvider: DispatcherProvider, dispatcherProvider: DispatcherProvider,
private val monitorControl: MonitorControl, private val monitorControl: MonitorControl,
private val podMonitor: PodMonitor, private val podMonitor: PodMonitor,
@@ -74,7 +74,7 @@ class OverviewFragmentVM @Inject constructor(
monitorControl.startMonitor() monitorControl.startMonitor()
} }
} }
.map { Unit } .map { }
.asLiveData2() .asLiveData2()
val requestPermissionEvent = SingleLiveEvent<Permission>() val requestPermissionEvent = SingleLiveEvent<Permission>()
@@ -129,19 +129,13 @@ class OverviewFragmentVM @Inject constructor(
pods.map { pods.map {
val now = Instant.now() val now = Instant.now()
when (it) { when (it) {
is DualApplePods -> DualApplePodsCardVH.Item( is DualPodDevice -> DualPodsCardVH.Item(
now = now, now = now,
device = it, device = it,
showDebug = isDebugMode, showDebug = isDebugMode,
isMainPod = it == mainPod, isMainPod = it == mainPod,
) )
is SingleApplePods -> SingleApplePodsCardVH.Item( is SinglePodDevice -> SinglePodsCardVH.Item(
now = now,
device = it,
showDebug = isDebugMode,
isMainPod = it == mainPod,
)
is BasicSingleApplePods -> BasicSingleApplePodsCardVH.Item(
now = now, now = now,
device = it, device = it,
showDebug = isDebugMode, showDebug = isDebugMode,
@@ -1,58 +0,0 @@
package eu.darken.capod.main.ui.overview.cards.pods
import android.graphics.Typeface
import android.view.ViewGroup
import androidx.core.view.isGone
import eu.darken.capod.R
import eu.darken.capod.common.lists.binding
import eu.darken.capod.databinding.OverviewPodsAppleSingleBasicItemBinding
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
import eu.darken.capod.pods.core.getBatteryDrawable
import eu.darken.capod.pods.core.getBatteryLevelHeadset
import eu.darken.capod.pods.core.lastSeenFormatted
import java.time.Instant
class BasicSingleApplePodsCardVH(parent: ViewGroup) :
PodDeviceVH<BasicSingleApplePodsCardVH.Item, OverviewPodsAppleSingleBasicItemBinding>(
R.layout.overview_pods_apple_single_basic_item,
parent
) {
override val viewBinding = lazy { OverviewPodsAppleSingleBasicItemBinding.bind(itemView) }
override val onBindData = binding(payload = true) { item: Item ->
val device = item.device
name.apply {
text = device.getLabel(context)
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
else setTypeface(typeface, Typeface.NORMAL)
}
deviceIcon.setImageResource(device.iconRes)
lastSeen.text = device.lastSeenFormatted(item.now)
reception.text = item.getReceptionText()
batteryLabel.text = device.getBatteryLevelHeadset(context)
batteryIcon.setImageResource(getBatteryDrawable(device.batteryHeadsetPercent))
status.apply {
val sb = StringBuilder()
if (item.showDebug) {
sb.append("--- Debug ---")
sb.append("\n").append(device.rawDataHex)
}
text = sb
isGone = !item.showDebug
}
}
data class Item(
override val now: Instant,
override val device: BasicSingleApplePods,
override val showDebug: Boolean,
override val isMainPod: Boolean,
) : PodDeviceVH.Item
}
@@ -1,112 +0,0 @@
package eu.darken.capod.main.ui.overview.cards.pods
import android.graphics.Typeface
import android.view.ViewGroup
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import eu.darken.capod.R
import eu.darken.capod.common.lists.binding
import eu.darken.capod.databinding.OverviewPodsAppleDualItemBinding
import eu.darken.capod.pods.core.*
import eu.darken.capod.pods.core.apple.DualApplePods
import eu.darken.capod.pods.core.apple.DualApplePods.DeviceColor
import eu.darken.capod.pods.core.apple.DualApplePods.LidState
import java.time.Duration
import java.time.Instant
class DualApplePodsCardVH(parent: ViewGroup) :
PodDeviceVH<DualApplePodsCardVH.Item, OverviewPodsAppleDualItemBinding>(
R.layout.overview_pods_apple_dual_item,
parent
) {
override val viewBinding = lazy { OverviewPodsAppleDualItemBinding.bind(itemView) }
override val onBindData = binding(payload = true) { item: Item ->
val device = item.device
name.apply {
val sb = StringBuilder(device.getLabel(context))
if (!listOf(DeviceColor.WHITE, DeviceColor.UNKNOWN).contains(device.deviceColor)) {
sb.append(" (${device.deviceColor.name})")
}
text = sb
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
else setTypeface(typeface, Typeface.NORMAL)
if (item.showDebug) {
append(" [${device.primaryPod.name}]")
}
}
deviceIcon.setImageResource(device.iconRes)
lastSeen.text = context.getString(R.string.last_seen_x, device.lastSeenFormatted(item.now))
firstSeen.text = context.getString(R.string.first_seen_x, device.firstSeenFormatted(item.now))
firstSeen.isGone = Duration.between(device.seenFirstAt, device.seenLastAt).toMinutes() < 1
reception.text = item.getReceptionText()
// Left Pod
device.apply {
podLeftBatteryIcon.setImageResource(getBatteryDrawable(batteryLeftPodPercent))
podLeftBatteryLabel.text = getBatteryLevelLeftPod(context)
podLeftChargingIcon.isInvisible = !isLeftPodCharging
podLeftChargingLabel.isInvisible = !isLeftPodCharging
podLeftMicrophoneIcon.isInvisible = !isLeftPodMicrophone
podLeftMicrophoneLabel.isInvisible = !isLeftPodMicrophone
podLeftWearIcon.isInvisible = !isLeftPodInEar
podLeftWearLabel.isInvisible = !isLeftPodInEar
}
// Right Pod
device.apply {
podRightBatteryIcon.setImageResource(getBatteryDrawable(batteryRightPodPercent))
podRightBatteryLabel.text = getBatteryLevelRightPod(context)
podRightChargingIcon.isInvisible = !isRightPodCharging
podRightChargingLabel.isInvisible = !isRightPodCharging
podRightMicrophoneIcon.isInvisible = !isRightPodMicrophone
podRightMicrophoneLabel.isInvisible = !isRightPodMicrophone
podRightWearIcon.isInvisible = !isRightPodInEar
podRightWearLabel.isInvisible = !isRightPodInEar
}
// Case
device.apply {
podCaseBatteryIcon.setImageResource(getBatteryDrawable(batteryCasePercent))
podCaseBatteryLabel.text = getBatteryLevelCase(context)
podCaseChargingIcon.isInvisible = !isCaseCharging
podCaseChargingLabel.isInvisible = !isCaseCharging
podCaseLidLabel.text = when (caseLidState) {
LidState.OPEN -> context.getString(R.string.pods_case_status_open_label)
LidState.CLOSED -> context.getString(R.string.pods_case_status_closed_label)
else -> context.getString(R.string.pods_case_unknown_state)
}
val hideInfo = !listOf(LidState.OPEN, LidState.CLOSED).contains(caseLidState)
podCaseLidIcon.isInvisible = hideInfo
podCaseLidLabel.isInvisible = hideInfo
}
status.apply {
val sb = StringBuilder(device.getConnectionStateLabel(context))
if (item.showDebug) {
sb.append("\n\n").append("---Debug---")
sb.append("\n").append(device.rawDataHex)
}
text = sb
}
}
data class Item(
override val now: Instant,
override val device: DualApplePods,
override val showDebug: Boolean,
override val isMainPod: Boolean,
) : PodDeviceVH.Item
}
@@ -0,0 +1,166 @@
package eu.darken.capod.main.ui.overview.cards.pods
import android.graphics.Typeface
import android.view.ViewGroup
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import eu.darken.capod.R
import eu.darken.capod.common.lists.binding
import eu.darken.capod.databinding.OverviewPodsDualItemBinding
import eu.darken.capod.pods.core.*
import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualAirPods.LidState
import java.time.Duration
import java.time.Instant
class DualPodsCardVH(parent: ViewGroup) :
PodDeviceVH<DualPodsCardVH.Item, OverviewPodsDualItemBinding>(
R.layout.overview_pods_dual_item,
parent
) {
override val viewBinding = lazy { OverviewPodsDualItemBinding.bind(itemView) }
override val onBindData = binding(payload = true) { item: Item ->
val device = item.device
name.apply {
val sb = StringBuilder(device.getLabel(context))
if (device is HasPodStyle && item.showDebug) {
val style = device.podStyle
sb.append(" (${style.getColor(context)})")
}
text = sb
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
else setTypeface(typeface, Typeface.NORMAL)
if (device is DualAirPods && item.showDebug) {
append(" [${device.primaryPod.name}]")
}
}
deviceIcon.setImageResource(device.iconRes)
lastSeen.text = context.getString(R.string.last_seen_x, device.lastSeenFormatted(item.now))
firstSeen.text = context.getString(R.string.first_seen_x, device.firstSeenFormatted(item.now))
firstSeen.isGone = Duration.between(device.seenFirstAt, device.seenLastAt).toMinutes() < 1
reception.text = item.getReceptionText()
// Pods battery state
device.apply {
podLeftBatteryIcon.setImageResource(getBatteryDrawable(batteryLeftPodPercent))
podLeftBatteryLabel.text = getBatteryLevelLeftPod(context)
podRightBatteryIcon.setImageResource(getBatteryDrawable(batteryRightPodPercent))
podRightBatteryLabel.text = getBatteryLevelRightPod(context)
}
// Pods charging state
device.apply {
if (this is HasChargeDetectionDual) {
podLeftChargingIcon.isInvisible = !isLeftPodCharging
podLeftChargingLabel.isInvisible = !isLeftPodCharging
podRightChargingIcon.isInvisible = !isRightPodCharging
podRightChargingLabel.isInvisible = !isRightPodCharging
} else {
podLeftChargingIcon.isGone = true
podLeftChargingLabel.isGone = true
podRightChargingIcon.isGone = true
podRightChargingLabel.isGone = true
}
}
// Microphone state
device.apply {
if (this is HasDualMicrophone) {
podLeftMicrophoneIcon.isInvisible = !isLeftPodMicrophone
podLeftMicrophoneLabel.isInvisible = !isLeftPodMicrophone
podRightMicrophoneIcon.isInvisible = !isRightPodMicrophone
podRightMicrophoneLabel.isInvisible = !isRightPodMicrophone
} else {
podLeftMicrophoneIcon.isGone = true
podLeftMicrophoneLabel.isGone = true
podRightMicrophoneIcon.isGone = true
podRightMicrophoneLabel.isGone = true
}
}
// Pods wear state
device.apply {
if (this is HasEarDetectionDual) {
podLeftWearIcon.isInvisible = !isLeftPodInEar
podLeftWearLabel.isInvisible = !isLeftPodInEar
podRightWearIcon.isInvisible = !isRightPodInEar
podRightWearLabel.isInvisible = !isRightPodInEar
} else {
podLeftWearIcon.isGone = true
podLeftWearLabel.isGone = true
podRightWearIcon.isGone = true
podRightWearLabel.isGone = true
}
}
// Case charge state
device.apply {
if (this is HasCase) {
podCaseBatteryIcon.isGone = false
podCaseBatteryIcon.setImageResource(getBatteryDrawable(batteryCasePercent))
podCaseBatteryLabel.text = getBatteryLevelCase(context)
podCaseChargingIcon.isInvisible = !isCaseCharging
podCaseChargingLabel.isInvisible = !isCaseCharging
} else {
podCaseBatteryIcon.isGone = true
podCaseBatteryLabel.isGone = true
podCaseChargingIcon.isGone = true
podCaseChargingLabel.isGone = true
}
}
// Case lid state
device.apply {
if (this is DualAirPods) {
podCaseLidLabel.text = when (caseLidState) {
LidState.OPEN -> context.getString(R.string.pods_case_status_open_label)
LidState.CLOSED -> context.getString(R.string.pods_case_status_closed_label)
else -> context.getString(R.string.pods_case_unknown_state)
}
val hideInfo = !listOf(LidState.OPEN, LidState.CLOSED).contains(caseLidState)
podCaseLidIcon.isInvisible = hideInfo
podCaseLidLabel.isInvisible = hideInfo
} else {
podCaseLidIcon.isGone = true
podCaseLidLabel.isGone = true
}
}
// Connection state
device.apply {
val sb = StringBuilder()
if (this is HasStateDetection) {
sb.append(state.getLabel(context))
}
if (item.showDebug) {
sb.append("\n\n").append("---Debug---")
sb.append("\n").append(rawDataHex)
}
status.text = sb
status.isGone = sb.isEmpty()
}
}
data class Item(
override val now: Instant,
override val device: DualPodDevice,
override val showDebug: Boolean,
override val isMainPod: Boolean,
) : PodDeviceVH.Item
}
@@ -1,65 +0,0 @@
package eu.darken.capod.main.ui.overview.cards.pods
import android.graphics.Typeface
import android.view.ViewGroup
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import eu.darken.capod.R
import eu.darken.capod.common.lists.binding
import eu.darken.capod.databinding.OverviewPodsAppleSingleItemBinding
import eu.darken.capod.pods.core.apple.SingleApplePods
import eu.darken.capod.pods.core.getBatteryDrawable
import eu.darken.capod.pods.core.getBatteryLevelHeadset
import eu.darken.capod.pods.core.lastSeenFormatted
import java.time.Instant
class SingleApplePodsCardVH(parent: ViewGroup) :
PodDeviceVH<SingleApplePodsCardVH.Item, OverviewPodsAppleSingleItemBinding>(
R.layout.overview_pods_apple_single_item,
parent
) {
override val viewBinding = lazy { OverviewPodsAppleSingleItemBinding.bind(itemView) }
override val onBindData = binding(payload = true) { item: Item ->
val device = item.device
name.apply {
text = device.getLabel(context)
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
else setTypeface(typeface, Typeface.NORMAL)
}
deviceIcon.setImageResource(device.iconRes)
lastSeen.text = device.lastSeenFormatted(item.now)
reception.text = item.getReceptionText()
batteryLabel.text = device.getBatteryLevelHeadset(context)
batteryIcon.setImageResource(getBatteryDrawable(device.batteryHeadsetPercent))
chargingIcon.isInvisible = device.isHeadsetBeingCharged
chargingLabel.isInvisible = device.isHeadsetBeingCharged
wearIcon.isInvisible = device.isHeadphonesBeingWorn
wearLabel.isInvisible = device.isHeadphonesBeingWorn
status.apply {
val sb = StringBuilder()
if (item.showDebug) {
sb.append("--- Debug ---")
sb.append("\n").append(device.rawDataHex)
}
text = sb
isGone = !item.showDebug
}
}
data class Item(
override val now: Instant,
override val device: SingleApplePods,
override val showDebug: Boolean,
override val isMainPod: Boolean,
) : PodDeviceVH.Item
}
@@ -0,0 +1,81 @@
package eu.darken.capod.main.ui.overview.cards.pods
import android.graphics.Typeface
import android.view.ViewGroup
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import eu.darken.capod.R
import eu.darken.capod.common.lists.binding
import eu.darken.capod.databinding.OverviewPodsSingleItemBinding
import eu.darken.capod.pods.core.*
import java.time.Instant
class SinglePodsCardVH(parent: ViewGroup) :
PodDeviceVH<SinglePodsCardVH.Item, OverviewPodsSingleItemBinding>(
R.layout.overview_pods_single_item,
parent
) {
override val viewBinding = lazy { OverviewPodsSingleItemBinding.bind(itemView) }
override val onBindData = binding(payload = true) { item: Item ->
val device = item.device
name.apply {
text = device.getLabel(context)
if (item.isMainPod) setTypeface(typeface, Typeface.BOLD)
else setTypeface(typeface, Typeface.NORMAL)
}
deviceIcon.setImageResource(device.iconRes)
lastSeen.text = device.lastSeenFormatted(item.now)
reception.text = item.getReceptionText()
// Battery level
device.apply {
batteryLabel.text = getBatteryLevelHeadset(context)
batteryIcon.setImageResource(getBatteryDrawable(batteryHeadsetPercent))
}
// Charge state
device.apply {
if (this is HasChargeDetection) {
chargingIcon.isInvisible = isHeadsetBeingCharged
chargingLabel.isInvisible = isHeadsetBeingCharged
} else {
chargingIcon.isGone = true
chargingLabel.isGone = true
}
}
// Has ear detection
device.apply {
if (this is HasEarDetection) {
wearIcon.isInvisible = isBeingWorn
wearLabel.isInvisible = isBeingWorn
} else {
wearIcon.isGone = true
wearLabel.isGone = true
}
}
status.apply {
val sb = StringBuilder()
if (item.showDebug) {
sb.append("--- Debug ---")
sb.append("\n").append(device.rawDataHex)
}
text = sb
isGone = !item.showDebug
}
}
data class Item(
override val now: Instant,
override val device: SinglePodDevice,
override val showDebug: Boolean,
override val isMainPod: Boolean,
) : PodDeviceVH.Item
}
@@ -66,6 +66,7 @@ class PodMonitor @Inject constructor(
) { scannerMode, compatMode, unfiltered -> ) { scannerMode, compatMode, unfiltered ->
Triple(scannerMode, compatMode, unfiltered) Triple(scannerMode, compatMode, unfiltered)
}.flatMapLatest { (mode, compat, unfiltered) -> }.flatMapLatest { (mode, compat, unfiltered) ->
log(TAG, VERBOSE) { "Starting BLEScanner mode=$mode, compat=$compat, unfiltered=$unfiltered" }
val filters = if (unfiltered) { val filters = if (unfiltered) {
setOf(getUnfilteredFilter()) setOf(getUnfilteredFilter())
} else { } else {
@@ -6,8 +6,7 @@ import android.widget.RemoteViews
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import eu.darken.capod.R import eu.darken.capod.R
import eu.darken.capod.pods.core.* import eu.darken.capod.pods.core.*
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualApplePods
import eu.darken.capod.pods.core.apple.SingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
import javax.inject.Inject import javax.inject.Inject
@@ -17,13 +16,12 @@ class MonitorNotificationViewFactory @Inject constructor(
) { ) {
fun createContentView(device: PodDevice): RemoteViews = when (device) { fun createContentView(device: PodDevice): RemoteViews = when (device) {
is DualApplePods -> createDualApplePods(device) is DualAirPods -> createDualApplePods(device)
is SingleApplePods -> createSingleApplePods(device) is SingleApplePods -> createSingleApplePods(device)
is BasicSingleApplePods -> createSingleBasicApplePods(device)
else -> createUnknownDevice(device) else -> createUnknownDevice(device)
} }
private fun createDualApplePods(device: DualApplePods): RemoteViews = RemoteViews( private fun createDualApplePods(device: DualAirPods): RemoteViews = RemoteViews(
context.packageName, context.packageName,
R.layout.monitor_notification_dual_pods_small R.layout.monitor_notification_dual_pods_small
).apply { ).apply {
@@ -52,19 +50,12 @@ class MonitorNotificationViewFactory @Inject constructor(
setTextViewText(R.id.headphones_label, getLabel(context)) setTextViewText(R.id.headphones_label, getLabel(context))
setImageViewResource(R.id.headphones_battery_icon, getBatteryDrawable(batteryHeadsetPercent)) setImageViewResource(R.id.headphones_battery_icon, getBatteryDrawable(batteryHeadsetPercent))
setTextViewText(R.id.headphones_battery_label, getBatteryLevelHeadset(context)) setTextViewText(R.id.headphones_battery_label, getBatteryLevelHeadset(context))
setViewVisibility(R.id.headphones_charging, if (isHeadsetBeingCharged) View.VISIBLE else View.GONE) if (this is HasEarDetection) {
setViewVisibility(R.id.headphones_worn, if (isHeadphonesBeingWorn) View.VISIBLE else View.GONE) setViewVisibility(R.id.headphones_worn, if (isBeingWorn) View.VISIBLE else View.GONE)
} }
} if (this is HasChargeDetectionDual) {
setViewVisibility(R.id.headphones_charging, if (isHeadsetBeingCharged) View.VISIBLE else View.GONE)
private fun createSingleBasicApplePods(device: BasicSingleApplePods): RemoteViews = RemoteViews( }
context.packageName,
R.layout.monitor_notification_single_pods_basic_small
).apply {
device.apply {
setTextViewText(R.id.headphones_label, getLabel(context))
setImageViewResource(R.id.headphones_battery_icon, getBatteryDrawable(batteryHeadsetPercent))
setTextViewText(R.id.headphones_battery_label, getBatteryLevelHeadset(context))
} }
} }
@@ -1,6 +1,6 @@
package eu.darken.capod.pods.core package eu.darken.capod.pods.core
interface HasDualPods { interface DualPodDevice : PodDevice {
enum class Pod { enum class Pod {
LEFT, LEFT,
@@ -0,0 +1,7 @@
package eu.darken.capod.pods.core
interface HasChargeDetection {
val isHeadsetBeingCharged: Boolean
}
@@ -0,0 +1,14 @@
package eu.darken.capod.pods.core
interface HasChargeDetectionDual : HasChargeDetection {
val isLeftPodCharging: Boolean
val isRightPodCharging: Boolean
val isEitherPodCharging: Boolean
get() = isLeftPodCharging || isRightPodCharging
override val isHeadsetBeingCharged: Boolean
get() = isEitherPodCharging
}
@@ -0,0 +1,9 @@
package eu.darken.capod.pods.core
interface HasDualMicrophone {
val isLeftPodMicrophone: Boolean
val isRightPodMicrophone: Boolean
}
@@ -1,6 +1,6 @@
package eu.darken.capod.pods.core package eu.darken.capod.pods.core
interface HasEarDetection : PodDevice { interface HasEarDetection {
val isBeingWorn: Boolean val isBeingWorn: Boolean
@@ -1,6 +1,6 @@
package eu.darken.capod.pods.core package eu.darken.capod.pods.core
interface HasDualEarDetection : HasEarDetection { interface HasEarDetectionDual : HasEarDetection {
val isLeftPodInEar: Boolean val isLeftPodInEar: Boolean
@@ -0,0 +1,19 @@
package eu.darken.capod.pods.core
import android.content.Context
import androidx.annotation.ColorRes
interface HasPodStyle {
val podStyle: PodStyle
interface PodStyle {
fun getLabel(context: Context): String
@ColorRes
fun getColor(context: Context): Int
val identifier: String
}
}
@@ -0,0 +1,12 @@
package eu.darken.capod.pods.core
import android.content.Context
interface HasStateDetection {
val state: State
interface State {
fun getLabel(context: Context): String
}
}
@@ -100,6 +100,12 @@ interface PodDevice {
@Json(name = "beats.powerbeats.pro") POWERBEATS_PRO( @Json(name = "beats.powerbeats.pro") POWERBEATS_PRO(
"Power Beats Pro" "Power Beats Pro"
), ),
@Json(name = "fakes.tws.i99999") TWS_I99999(
"TWS i99999"
),
@Json(name = "fakes.varunr.airpodspro") VARUNR_AIRPODS_PRO(
"Varunr AirPods Pro"
),
@Json(name = "unknown") UNKNOWN( @Json(name = "unknown") UNKNOWN(
"Unknown" "Unknown"
); );
@@ -8,11 +8,11 @@ import java.time.Duration
import java.time.Instant import java.time.Instant
import kotlin.math.roundToInt import kotlin.math.roundToInt
fun HasDualPods.getBatteryLevelLeftPod(context: Context): String = fun DualPodDevice.getBatteryLevelLeftPod(context: Context): String =
batteryLeftPodPercent?.let { "${(it * 100).roundToInt()}%" } batteryLeftPodPercent?.let { "${(it * 100).roundToInt()}%" }
?: context.getString(R.string.general_value_not_available_label) ?: context.getString(R.string.general_value_not_available_label)
fun HasDualPods.getBatteryLevelRightPod(context: Context): String = fun DualPodDevice.getBatteryLevelRightPod(context: Context): String =
batteryRightPodPercent?.let { "${(it * 100).roundToInt()}%" } batteryRightPodPercent?.let { "${(it * 100).roundToInt()}%" }
?: context.getString(R.string.general_value_not_available_label) ?: context.getString(R.string.general_value_not_available_label)
@@ -20,7 +20,7 @@ fun HasCase.getBatteryLevelCase(context: Context): String =
batteryCasePercent?.let { "${(it * 100).roundToInt()}%" } batteryCasePercent?.let { "${(it * 100).roundToInt()}%" }
?: context.getString(R.string.general_value_not_available_label) ?: context.getString(R.string.general_value_not_available_label)
fun HasSinglePod.getBatteryLevelHeadset(context: Context): String = fun SinglePodDevice.getBatteryLevelHeadset(context: Context): String =
batteryHeadsetPercent?.let { "${(it * 100).roundToInt()}%" } batteryHeadsetPercent?.let { "${(it * 100).roundToInt()}%" }
?: context.getString(R.string.general_value_not_available_label) ?: context.getString(R.string.general_value_not_available_label)
@@ -1,6 +1,6 @@
package eu.darken.capod.pods.core package eu.darken.capod.pods.core
interface HasSinglePod { interface SinglePodDevice : PodDevice {
val batteryHeadsetPercent: Float? val batteryHeadsetPercent: Float?
} }
@@ -1,12 +1,12 @@
package eu.darken.capod.pods.core.apple package eu.darken.capod.pods.core.apple
import eu.darken.capod.common.bluetooth.BleScanResult import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.Bugs
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
import eu.darken.capod.common.debug.logging.asLog import eu.darken.capod.common.debug.logging.asLog
import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.misc.UnknownAppleDevice
import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
@@ -54,25 +54,13 @@ class AppleFactory @Inject constructor(
val factory = podFactories.firstOrNull { it.isResponsible(pm) } val factory = podFactories.firstOrNull { it.isResponsible(pm) }
val device = (factory ?: unknownAppleFactory).create( return@withLock (factory ?: unknownAppleFactory).create(
scanResult = scanResult, scanResult = scanResult,
proximityMessage = pm, message = pm,
) )
if (factory == null && !SILENCED_PMS.contains(device.rawDeviceModel) && scanResult.address != "6E:9E:D1:49:D2:6D") {
SILENCED_PMS.add(device.rawDeviceModel)
Bugs.report(
tag = TAG,
message = "Unknown proximity message type",
exception = IllegalArgumentException("Unknown ProximityMessage: $pm")
)
}
return@withLock device
} }
companion object { companion object {
private val SILENCED_PMS = mutableSetOf<UShort>()
private val TAG = logTag("Pod", "Apple", "Factory") private val TAG = logTag("Pod", "Apple", "Factory")
} }
} }
@@ -7,6 +7,8 @@ import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoSet import dagger.multibindings.IntoSet
import eu.darken.capod.pods.core.apple.airpods.* import eu.darken.capod.pods.core.apple.airpods.*
import eu.darken.capod.pods.core.apple.beats.* import eu.darken.capod.pods.core.apple.beats.*
import eu.darken.capod.pods.core.apple.misc.Twsi99999
import eu.darken.capod.pods.core.apple.misc.VarunrAirPodsPro
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
@Module @Module
@@ -25,4 +27,8 @@ abstract class AppleFactoryModule {
@Binds @IntoSet abstract fun beatsX(factory: BeatsX.Factory): ApplePodsFactory<out ApplePods> @Binds @IntoSet abstract fun beatsX(factory: BeatsX.Factory): ApplePodsFactory<out ApplePods>
@Binds @IntoSet abstract fun powerBeats3(factory: PowerBeats3.Factory): ApplePodsFactory<out ApplePods> @Binds @IntoSet abstract fun powerBeats3(factory: PowerBeats3.Factory): ApplePodsFactory<out ApplePods>
@Binds @IntoSet abstract fun powerBeatsPro(factory: PowerBeatsPro.Factory): ApplePodsFactory<out ApplePods> @Binds @IntoSet abstract fun powerBeatsPro(factory: PowerBeatsPro.Factory): ApplePodsFactory<out ApplePods>
@Binds @IntoSet abstract fun fakesTwsi999999(factory: Twsi99999.Factory): ApplePodsFactory<out ApplePods>
@Binds @IntoSet
abstract fun fakesVarunrAirPodsPro(factory: VarunrAirPodsPro.Factory): ApplePodsFactory<out ApplePods>
} }
@@ -5,7 +5,9 @@ import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.lowerNibble import eu.darken.capod.common.lowerNibble
import eu.darken.capod.common.upperNibble import eu.darken.capod.common.upperNibble
import eu.darken.capod.pods.core.HasCase
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.airpods.AirPodsPro
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
@@ -21,9 +23,9 @@ abstract class ApplePodsFactory<PodType : ApplePods>(private val tag: String) {
val deviceColor: UByte, val deviceColor: UByte,
) )
fun ProximityPairing.Message.getApplePodsMarkings(): Markings = Markings( private fun ProximityPairing.Message.getApplePodsMarkings(): Markings = Markings(
vendor = ProximityPairing.CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING, vendor = ProximityPairing.CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING,
length = ProximityPairing.PROXIMITY_PAIRING_MESSAGE_LENGTH.toUByte(), length = ProximityPairing.PAIRING_MESSAGE_LENGTH.toUByte(),
device = (((data[1].toInt() and 255) shl 8) or (data[2].toInt() and 255)).toUShort(), device = (((data[1].toInt() and 255) shl 8) or (data[2].toInt() and 255)).toUShort(),
// Make comparison order independent // Make comparison order independent
podBatteryData = setOf(data[4].upperNibble, data[4].lowerNibble), podBatteryData = setOf(data[4].upperNibble, data[4].lowerNibble),
@@ -70,6 +72,22 @@ abstract class ApplePodsFactory<PodType : ApplePods>(private val tag: String) {
internal val knownDevices = mutableMapOf<PodDevice.Id, KnownDevice>() internal val knownDevices = mutableMapOf<PodDevice.Id, KnownDevice>()
fun KnownDevice.getLatestCaseBattery(): Float? = history
.filterIsInstance<HasCase>()
.mapNotNull { it.batteryCasePercent }
.lastOrNull()
fun KnownDevice.getLatestCaseLidState(basic: DualAirPods): DualAirPods.LidState? {
val definitive = setOf(DualAirPods.LidState.OPEN, DualAirPods.LidState.CLOSED)
if (definitive.contains(basic.caseLidState)) return null
return history
.filterIsInstance<AirPodsPro>()
.lastOrNull { it.caseLidState != DualAirPods.LidState.NOT_IN_CASE }
?.caseLidState
}
internal open fun searchHistory(current: PodType): KnownDevice? { internal open fun searchHistory(current: PodType): KnownDevice? {
val scanResult = current.scanResult val scanResult = current.scanResult
val message = current.proximityMessage val message = current.proximityMessage
@@ -138,10 +156,10 @@ abstract class ApplePodsFactory<PodType : ApplePods>(private val tag: String) {
dirty = data[1] dirty = data[1]
) )
abstract fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean abstract fun isResponsible(message: ProximityPairing.Message): Boolean
abstract fun create( abstract fun create(
scanResult: BleScanResult, scanResult: BleScanResult,
proximityMessage: ProximityPairing.Message, message: ProximityPairing.Message,
): ApplePods ): ApplePods
} }
@@ -1,19 +0,0 @@
package eu.darken.capod.pods.core.apple
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.lowerNibble
import eu.darken.capod.pods.core.HasSinglePod
interface BasicSingleApplePods : ApplePods, HasSinglePod {
override val batteryHeadsetPercent: Float?
get() = when (val value = rawPodsBattery.lowerNibble.toInt()) {
15 -> null
else -> if (value > 10) {
log { "Left pod: Above 100% battery: $value" }
1.0f
} else {
(value / 10f)
}
}
}
@@ -1,3 +0,0 @@
package eu.darken.capod.pods.core.apple
abstract class BasicSingleApplePodsFactory(private val tag: String) : ApplePodsFactory<BasicSingleApplePods>(tag)
@@ -7,12 +7,11 @@ import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.isBitSet import eu.darken.capod.common.isBitSet
import eu.darken.capod.common.lowerNibble import eu.darken.capod.common.lowerNibble
import eu.darken.capod.common.upperNibble import eu.darken.capod.common.upperNibble
import eu.darken.capod.pods.core.HasCase import eu.darken.capod.pods.core.*
import eu.darken.capod.pods.core.HasDualEarDetection import eu.darken.capod.pods.core.DualPodDevice.Pod
import eu.darken.capod.pods.core.HasDualPods
import eu.darken.capod.pods.core.HasDualPods.Pod
interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase { interface DualAirPods : ApplePods, HasChargeDetectionDual, DualPodDevice, HasEarDetectionDual, HasCase,
HasStateDetection, HasDualMicrophone, HasAppleColor {
val primaryPod: Pod val primaryPod: Pod
get() = when (rawStatus.isBitSet(5)) { get() = when (rawStatus.isBitSet(5)) {
@@ -86,23 +85,23 @@ interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
* The data flip bit is set if the left pod is primary. * The data flip bit is set if the left pod is primary.
* For the pod that is in the case, this is flipped again though. * For the pod that is in the case, this is flipped again though.
*/ */
val isLeftPodMicrophone: Boolean override val isLeftPodMicrophone: Boolean
get() = rawStatus.isBitSet(5) xor isThisPodInThecase get() = rawStatus.isBitSet(5) xor isThisPodInThecase
/** /**
* The data flip bit is UNset if the right pod is primary. * The data flip bit is UNset if the right pod is primary.
* For the pod that is in the case, this is flipped again though. * For the pod that is in the case, this is flipped again though.
*/ */
val isRightPodMicrophone: Boolean override val isRightPodMicrophone: Boolean
get() = !rawStatus.isBitSet(5) xor isThisPodInThecase get() = !rawStatus.isBitSet(5) xor isThisPodInThecase
val isLeftPodCharging: Boolean override val isLeftPodCharging: Boolean
get() = when (areValuesFlipped) { get() = when (areValuesFlipped) {
false -> rawFlags.isBitSet(0) false -> rawFlags.isBitSet(0)
true -> rawFlags.isBitSet(1) true -> rawFlags.isBitSet(1)
} }
val isRightPodCharging: Boolean override val isRightPodCharging: Boolean
get() = when (areValuesFlipped) { get() = when (areValuesFlipped) {
false -> rawFlags.isBitSet(1) false -> rawFlags.isBitSet(1)
true -> rawFlags.isBitSet(0) true -> rawFlags.isBitSet(0)
@@ -143,35 +142,10 @@ interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
UNKNOWN(0xFF..0xFF); UNKNOWN(0xFF..0xFF);
} }
val deviceColor: DeviceColor override val state: ConnectionState
get() = DeviceColor.values().firstOrNull { it.raw == rawDeviceColor } ?: DeviceColor.UNKNOWN
enum class DeviceColor(val raw: UByte?) {
WHITE(0x00),
BLACK(0x01),
RED(0x02),
BLUE(0x03),
PINK(0x04),
GRAY(0x05),
SILVER(0x06),
GOLD(0x07),
ROSE_GOLD(0x08),
SPACE_GRAY(0x09),
DARK_BLUE(0x0a),
LIGHT_BLUE(0x0b),
YELLOW(0x0c),
UNKNOWN(null);
constructor(raw: Int) : this(raw.toUByte())
}
val connectionState: ConnectionState
get() = ConnectionState.values().firstOrNull { rawSuffix == it.raw } ?: ConnectionState.UNKNOWN get() = ConnectionState.values().firstOrNull { rawSuffix == it.raw } ?: ConnectionState.UNKNOWN
fun getConnectionStateLabel(context: Context): String = context.getString(connectionState.labelRes) enum class ConnectionState(val raw: UByte?, @StringRes val labelRes: Int) : HasStateDetection.State {
enum class ConnectionState(val raw: UByte?, @StringRes val labelRes: Int) {
DISCONNECTED(0x00, R.string.pods_connection_state_disconnected_label), DISCONNECTED(0x00, R.string.pods_connection_state_disconnected_label),
IDLE(0x04, R.string.pods_connection_state_idle_label), IDLE(0x04, R.string.pods_connection_state_idle_label),
MUSIC(0x05, R.string.pods_connection_state_music_label), MUSIC(0x05, R.string.pods_connection_state_music_label),
@@ -180,6 +154,8 @@ interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
HANGING_UP(0x09, R.string.pods_connection_state_hanging_up_label), HANGING_UP(0x09, R.string.pods_connection_state_hanging_up_label),
UNKNOWN(null, R.string.pods_connection_state_unknown_label); UNKNOWN(null, R.string.pods_connection_state_unknown_label);
override fun getLabel(context: Context): String = context.getString(labelRes)
constructor(raw: Int, @StringRes labelRes: Int) : this(raw.toUByte(), labelRes) constructor(raw: Int, @StringRes labelRes: Int) : this(raw.toUByte(), labelRes)
} }
@@ -3,18 +3,17 @@ package eu.darken.capod.pods.core.apple
import eu.darken.capod.common.debug.logging.Logging.Priority.DEBUG import eu.darken.capod.common.debug.logging.Logging.Priority.DEBUG
import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.airpods.AirPodsPro
abstract class DualApplePodsFactory(private val tag: String) : ApplePodsFactory<DualApplePods>(tag) { abstract class DualApplePodsFactory(private val tag: String) : ApplePodsFactory<DualAirPods>(tag) {
fun DualApplePods.getCaseMatchMarkings() = SplitPodsMarkings( fun DualAirPods.getCaseMatchMarkings() = SplitPodsMarkings(
leftPodBattery = batteryLeftPodPercent, leftPodBattery = batteryLeftPodPercent,
rightPodBattery = batteryRightPodPercent, rightPodBattery = batteryRightPodPercent,
microPhoneLeft = isLeftPodMicrophone, microPhoneLeft = isLeftPodMicrophone,
microPhoneRight = isRightPodMicrophone, microPhoneRight = isRightPodMicrophone,
chargingLeft = isLeftPodCharging, chargingLeft = isLeftPodCharging,
chargingRight = isRightPodCharging, chargingRight = isRightPodCharging,
color = deviceColor, color = rawDeviceColor,
model = model model = model
) )
@@ -28,36 +27,21 @@ abstract class DualApplePodsFactory(private val tag: String) : ApplePodsFactory<
val microPhoneRight: Boolean, val microPhoneRight: Boolean,
val chargingLeft: Boolean, val chargingLeft: Boolean,
val chargingRight: Boolean, val chargingRight: Boolean,
val color: DualApplePods.DeviceColor, val color: UByte,
val model: PodDevice.Model, val model: PodDevice.Model,
) )
private fun Collection<KnownDevice>.findSplitPodsMatch(device: DualApplePods): Collection<KnownDevice> { private fun Collection<KnownDevice>.findSplitPodsMatch(device: DualAirPods): Collection<KnownDevice> {
val target = device.getCaseMatchMarkings() val target = device.getCaseMatchMarkings()
return filter { known -> return filter { known ->
known.history known.history
.filterIsInstance<DualApplePods>() .filterIsInstance<DualAirPods>()
.any { it.getCaseMatchMarkings() == target } .any { it.getCaseMatchMarkings() == target }
} }
} }
fun KnownDevice.getLatestCaseBattery(): Float? = history override fun searchHistory(current: DualAirPods): KnownDevice? {
.filterIsInstance<DualApplePods>()
.mapNotNull { it.batteryCasePercent }
.lastOrNull()
fun KnownDevice.getLatestCaseLidState(basic: DualApplePods): DualApplePods.LidState? {
val definitive = setOf(DualApplePods.LidState.OPEN, DualApplePods.LidState.CLOSED)
if (definitive.contains(basic.caseLidState)) return null
return history
.filterIsInstance<AirPodsPro>()
.lastOrNull { it.caseLidState != DualApplePods.LidState.NOT_IN_CASE }
?.caseLidState
}
override fun searchHistory(current: DualApplePods): KnownDevice? {
val basicResult = super.searchHistory(current) val basicResult = super.searchHistory(current)
val caseIgnored = knownDevices.values.findSplitPodsMatch(current) val caseIgnored = knownDevices.values.findSplitPodsMatch(current)
@@ -0,0 +1,38 @@
package eu.darken.capod.pods.core.apple
import android.content.Context
import eu.darken.capod.pods.core.HasPodStyle
interface HasAppleColor : ApplePods, HasPodStyle {
override val podStyle: HasPodStyle.PodStyle
get() = DeviceColor.values()
.firstOrNull { it.raw == rawDeviceColor }
?: DeviceColor.UNKNOWN
enum class DeviceColor(val raw: UByte?) : HasPodStyle.PodStyle {
WHITE(0x00),
BLACK(0x01),
RED(0x02),
BLUE(0x03),
PINK(0x04),
GRAY(0x05),
SILVER(0x06),
GOLD(0x07),
ROSE_GOLD(0x08),
SPACE_GRAY(0x09),
DARK_BLUE(0x0a),
LIGHT_BLUE(0x0b),
YELLOW(0x0c),
UNKNOWN(null);
override fun getLabel(context: Context): String = this.name
override fun getColor(context: Context): Int = android.R.color.white
override val identifier: String
get() = name
constructor(raw: Int) : this(raw.toUByte())
}
}
@@ -1,17 +1,22 @@
package eu.darken.capod.pods.core.apple package eu.darken.capod.pods.core.apple
import eu.darken.capod.common.isBitSet import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.pods.core.HasEarDetection import eu.darken.capod.common.lowerNibble
import eu.darken.capod.pods.core.HasSinglePod import eu.darken.capod.pods.core.SinglePodDevice
interface SingleApplePods : BasicSingleApplePods, HasEarDetection, HasSinglePod { /**
* Devices that only present a single charge level, e.g. most Beats devices
*/
interface SingleApplePods : ApplePods, SinglePodDevice, HasAppleColor {
val isHeadphonesBeingWorn: Boolean override val batteryHeadsetPercent: Float?
get() = rawStatus.isBitSet(1) get() = when (val value = rawPodsBattery.lowerNibble.toInt()) {
15 -> null
val isHeadsetBeingCharged: Boolean else -> if (value > 10) {
get() = rawFlags.isBitSet(0) log { "Headset above 100% battery: $value" }
1.0f
override val isBeingWorn: Boolean } else {
get() = isHeadphonesBeingWorn (value / 10f)
}
}
} }
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualApplePodsFactory import eu.darken.capod.pods.core.apple.DualApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
@@ -20,15 +20,15 @@ data class AirPodsGen1 constructor(
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
private val cachedBatteryPercentage: Float? = null, private val cachedBatteryPercentage: Float? = null,
private val cachedCaseState: DualApplePods.LidState? = null private val cachedCaseState: DualAirPods.LidState? = null
) : DualApplePods { ) : DualAirPods {
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN1 override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN1
override val batteryCasePercent: Float? override val batteryCasePercent: Float?
get() = super.batteryCasePercent ?: cachedBatteryPercentage get() = super.batteryCasePercent ?: cachedBatteryPercentage
override val caseLidState: DualApplePods.LidState override val caseLidState: DualAirPods.LidState
get() = cachedCaseState ?: super.caseLidState get() = cachedCaseState ?: super.caseLidState
override val rssi: Int override val rssi: Int
@@ -36,11 +36,13 @@ data class AirPodsGen1 constructor(
class Factory @Inject constructor() : DualApplePodsFactory(TAG) { class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods {
var basic = AirPodsGen1(scanResult = scanResult, proximityMessage = proximityMessage) override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = AirPodsGen1(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualApplePodsFactory import eu.darken.capod.pods.core.apple.DualApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
@@ -20,15 +20,15 @@ data class AirPodsGen2 constructor(
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
private val cachedBatteryPercentage: Float? = null, private val cachedBatteryPercentage: Float? = null,
private val cachedCaseState: DualApplePods.LidState? = null private val cachedCaseState: DualAirPods.LidState? = null
) : DualApplePods { ) : DualAirPods {
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN2 override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN2
override val batteryCasePercent: Float? override val batteryCasePercent: Float?
get() = super.batteryCasePercent ?: cachedBatteryPercentage get() = super.batteryCasePercent ?: cachedBatteryPercentage
override val caseLidState: DualApplePods.LidState override val caseLidState: DualAirPods.LidState
get() = cachedCaseState ?: super.caseLidState get() = cachedCaseState ?: super.caseLidState
override val rssi: Int override val rssi: Int
@@ -36,11 +36,12 @@ data class AirPodsGen2 constructor(
class Factory @Inject constructor() : DualApplePodsFactory(TAG) { class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = AirPodsGen2(scanResult = scanResult, proximityMessage = proximityMessage) var basic = AirPodsGen2(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualApplePodsFactory import eu.darken.capod.pods.core.apple.DualApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
@@ -20,14 +20,14 @@ data class AirPodsGen3 constructor(
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
private val cachedBatteryPercentage: Float? = null, private val cachedBatteryPercentage: Float? = null,
private val cachedCaseState: DualApplePods.LidState? = null private val cachedCaseState: DualAirPods.LidState? = null
) : DualApplePods { ) : DualAirPods {
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN3 override val model: PodDevice.Model = PodDevice.Model.AIRPODS_GEN3
override val batteryCasePercent: Float? override val batteryCasePercent: Float?
get() = super.batteryCasePercent ?: cachedBatteryPercentage get() = super.batteryCasePercent ?: cachedBatteryPercentage
override val caseLidState: DualApplePods.LidState override val caseLidState: DualAirPods.LidState
get() = cachedCaseState ?: super.caseLidState get() = cachedCaseState ?: super.caseLidState
override val rssi: Int override val rssi: Int
@@ -35,11 +35,12 @@ data class AirPodsGen3 constructor(
class Factory @Inject constructor() : DualApplePodsFactory(TAG) { class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = AirPodsGen3(scanResult = scanResult, proximityMessage = proximityMessage) var basic = AirPodsGen3(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -2,6 +2,8 @@ package eu.darken.capod.pods.core.apple.airpods
import eu.darken.capod.common.bluetooth.BleScanResult import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.isBitSet
import eu.darken.capod.pods.core.HasEarDetection
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.SingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
@@ -19,20 +21,30 @@ data class AirPodsMax(
override val proximityMessage: ProximityPairing.Message, override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
) : SingleApplePods { ) : SingleApplePods, HasEarDetection {
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_MAX override val model: PodDevice.Model = PodDevice.Model.AIRPODS_MAX
override val rssi: Int override val rssi: Int
get() = rssiAverage ?: super.rssi get() = rssiAverage ?: super.rssi
val isHeadphonesBeingWorn: Boolean
get() = rawStatus.isBitSet(1)
val isHeadsetBeingCharged: Boolean
get() = rawFlags.isBitSet(0)
override val isBeingWorn: Boolean
get() = isHeadphonesBeingWorn
class Factory @Inject constructor() : SingleApplePodsFactory(TAG) { class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().dirty == DEVICE_CODE_DIRTY getModelInfo().dirty == DEVICE_CODE_DIRTY && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = AirPodsMax(scanResult = scanResult, proximityMessage = proximityMessage) var basic = AirPodsMax(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -48,7 +60,6 @@ data class AirPodsMax(
rssiAverage = result.averageRssi(basic.rssi), rssiAverage = result.averageRssi(basic.rssi),
) )
} }
} }
companion object { companion object {
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualApplePods.LidState import eu.darken.capod.pods.core.apple.DualAirPods.LidState
import eu.darken.capod.pods.core.apple.DualApplePodsFactory import eu.darken.capod.pods.core.apple.DualApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
@@ -22,7 +22,7 @@ data class AirPodsPro(
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
private val cachedBatteryPercentage: Float? = null, private val cachedBatteryPercentage: Float? = null,
private val cachedCaseState: LidState? = null private val cachedCaseState: LidState? = null
) : DualApplePods { ) : DualAirPods {
override val model: PodDevice.Model = PodDevice.Model.AIRPODS_PRO override val model: PodDevice.Model = PodDevice.Model.AIRPODS_PRO
@@ -37,11 +37,12 @@ data class AirPodsPro(
class Factory @Inject constructor() : DualApplePodsFactory(TAG) { class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = AirPodsPro(scanResult = scanResult, proximityMessage = proximityMessage) var basic = AirPodsPro(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
@@ -19,20 +19,21 @@ data class BeatsFlex(
override val proximityMessage: ProximityPairing.Message, override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
) : BasicSingleApplePods { ) : SingleApplePods {
override val model: PodDevice.Model = PodDevice.Model.BEATS_FLEX override val model: PodDevice.Model = PodDevice.Model.BEATS_FLEX
override val rssi: Int override val rssi: Int
get() = rssiAverage ?: super.rssi get() = rssiAverage ?: super.rssi
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) { class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = BeatsFlex(scanResult = scanResult, proximityMessage = proximityMessage) var basic = BeatsFlex(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
@@ -19,19 +19,20 @@ data class BeatsSolo3(
override val proximityMessage: ProximityPairing.Message, override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
) : BasicSingleApplePods { ) : SingleApplePods {
override val model: PodDevice.Model = PodDevice.Model.BEATS_SOLO_3 override val model: PodDevice.Model = PodDevice.Model.BEATS_SOLO_3
override val rssi: Int override val rssi: Int
get() = rssiAverage ?: super.rssi get() = rssiAverage ?: super.rssi
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) { class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = BeatsSolo3(scanResult = scanResult, proximityMessage = proximityMessage) var basic = BeatsSolo3(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
@@ -19,17 +19,18 @@ data class BeatsStudio3(
override val proximityMessage: ProximityPairing.Message, override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
) : BasicSingleApplePods { ) : SingleApplePods {
override val model: PodDevice.Model = PodDevice.Model.BEATS_STUDIO_3 override val model: PodDevice.Model = PodDevice.Model.BEATS_STUDIO_3
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) { class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().dirty == DEVICE_CODE_DIRTY getModelInfo().dirty == DEVICE_CODE_DIRTY && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = BeatsStudio3(scanResult = scanResult, proximityMessage = proximityMessage) var basic = BeatsStudio3(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -45,7 +46,6 @@ data class BeatsStudio3(
rssiAverage = result.averageRssi(basic.rssi), rssiAverage = result.averageRssi(basic.rssi),
) )
} }
} }
companion object { companion object {
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
@@ -19,20 +19,21 @@ data class BeatsX(
override val proximityMessage: ProximityPairing.Message, override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
) : BasicSingleApplePods { ) : SingleApplePods {
override val model: PodDevice.Model = PodDevice.Model.BEATS_X override val model: PodDevice.Model = PodDevice.Model.BEATS_X
override val rssi: Int override val rssi: Int
get() = rssiAverage ?: super.rssi get() = rssiAverage ?: super.rssi
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) { class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = BeatsX(scanResult = scanResult, proximityMessage = proximityMessage) var basic = BeatsX(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -4,8 +4,8 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
import eu.darken.capod.pods.core.apple.BasicSingleApplePodsFactory import eu.darken.capod.pods.core.apple.SingleApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
@@ -19,19 +19,21 @@ data class PowerBeats3(
override val proximityMessage: ProximityPairing.Message, override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
) : BasicSingleApplePods { ) : SingleApplePods {
override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_3 override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_3
override val rssi: Int override val rssi: Int
get() = rssiAverage ?: super.rssi get() = rssiAverage ?: super.rssi
class Factory @Inject constructor() : BasicSingleApplePodsFactory(TAG) { class Factory @Inject constructor() : SingleApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().full == DEVICE_CODE getModelInfo().full == DEVICE_CODE && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = PowerBeats3(scanResult = scanResult, proximityMessage = proximityMessage) var basic = PowerBeats3(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -4,7 +4,7 @@ import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualApplePodsFactory import eu.darken.capod.pods.core.apple.DualApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
@@ -20,15 +20,15 @@ data class PowerBeatsPro(
override val confidence: Float = PodDevice.BASE_CONFIDENCE, override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null, private val rssiAverage: Int? = null,
private val cachedBatteryPercentage: Float? = null, private val cachedBatteryPercentage: Float? = null,
private val cachedCaseState: DualApplePods.LidState? = null private val cachedCaseState: DualAirPods.LidState? = null
) : DualApplePods { ) : DualAirPods {
override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_PRO override val model: PodDevice.Model = PodDevice.Model.POWERBEATS_PRO
override val batteryCasePercent: Float? override val batteryCasePercent: Float?
get() = super.batteryCasePercent ?: cachedBatteryPercentage get() = super.batteryCasePercent ?: cachedBatteryPercentage
override val caseLidState: DualApplePods.LidState override val caseLidState: DualAirPods.LidState
get() = cachedCaseState ?: super.caseLidState get() = cachedCaseState ?: super.caseLidState
override val rssi: Int override val rssi: Int
@@ -36,11 +36,12 @@ data class PowerBeatsPro(
class Factory @Inject constructor() : DualApplePodsFactory(TAG) { class Factory @Inject constructor() : DualApplePodsFactory(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
proximityMessage.getModelInfo().dirty == DEVICE_CODE_DIRTY getModelInfo().dirty == DEVICE_CODE_DIRTY && length == ProximityPairing.PAIRING_MESSAGE_LENGTH
}
override fun create(scanResult: BleScanResult, proximityMessage: ProximityPairing.Message): ApplePods { override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = PowerBeatsPro(scanResult = scanResult, proximityMessage = proximityMessage) var basic = PowerBeatsPro(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -0,0 +1,143 @@
package eu.darken.capod.pods.core.apple.misc
import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.isBitSet
import eu.darken.capod.common.lowerNibble
import eu.darken.capod.common.upperNibble
import eu.darken.capod.pods.core.DualPodDevice
import eu.darken.capod.pods.core.HasCase
import eu.darken.capod.pods.core.HasDualMicrophone
import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.ApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant
import javax.inject.Inject
/**
* Basically an AirPods GEN1 clone
* Similar data structure but a lot of placeholder values or hardcoded values
*/
data class Twsi99999 constructor(
override val identifier: PodDevice.Id = PodDevice.Id(),
override val seenLastAt: Instant = Instant.now(),
override val seenFirstAt: Instant = Instant.now(),
override val seenCounter: Int = 1,
override val scanResult: BleScanResult,
override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null,
private val cachedBatteryPercentage: Float? = null,
) : ApplePods, DualPodDevice, HasDualMicrophone, HasCase {
override val model: PodDevice.Model = PodDevice.Model.TWS_I99999
override val rssi: Int
get() = rssiAverage ?: super<ApplePods>.rssi
/**
* Normally values for the left pod are in the lower nibbles, if the left pod is primary (microphone)
* If the right pod is the primary, the values are flipped.
*/
val areValuesFlipped: Boolean
get() = !rawStatus.isBitSet(5)
override val batteryLeftPodPercent: Float?
get() {
val value = when (areValuesFlipped) {
true -> rawPodsBattery.upperNibble.toInt()
false -> rawPodsBattery.lowerNibble.toInt()
}
return when (value) {
15 -> null
else -> if (value > 10) {
log { "Left pod: Above 100% battery: $value" }
1.0f
} else {
(value / 10f)
}
}
}
override val batteryRightPodPercent: Float?
get() {
val value = when (areValuesFlipped) {
true -> rawPodsBattery.lowerNibble.toInt()
false -> rawPodsBattery.upperNibble.toInt()
}
return when (value) {
15 -> null
else -> if (value > 10) {
log { "Right pod: Above 100% battery: $value" }
1.0f
} else {
value / 10f
}
}
}
val isThisPodInThecase: Boolean
get() = rawStatus.isBitSet(6)
/**
* The data flip bit is set if the left pod is primary.
* For the pod that is in the case, this is flipped again though.
*/
override val isLeftPodMicrophone: Boolean
get() = rawStatus.isBitSet(5) xor isThisPodInThecase
/**
* The data flip bit is UNset if the right pod is primary.
* For the pod that is in the case, this is flipped again though.
*/
override val isRightPodMicrophone: Boolean
get() = !rawStatus.isBitSet(5) xor isThisPodInThecase
override val batteryCasePercent: Float?
get() = when (val value = rawCaseBattery.toInt()) {
15 -> cachedBatteryPercentage
else -> if (value > 10) {
log { "Case: Above 100% battery: $value" }
1.0f
} else {
value / 10f
}
}
override val isCaseCharging: Boolean
get() = rawFlags.isBitSet(2)
class Factory @Inject constructor() : ApplePodsFactory<Twsi99999>(TAG) {
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
// Official message length is 19HEX, i.e. binary 25, did they copy this wrong?
getModelInfo().full == DEVICE_CODE && length == 19
}
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = Twsi99999(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id)
updateHistory(basic)
if (result == null) return basic
return basic.copy(
identifier = result.id,
seenFirstAt = result.seenFirstAt,
seenCounter = result.seenCounter,
confidence = result.confidence,
cachedBatteryPercentage = result.getLatestCaseBattery(),
rssiAverage = result.averageRssi(basic.rssi),
)
}
}
companion object {
private val DEVICE_CODE = 0x0220.toUShort()
private val TAG = logTag("PodDevice", "Apple", "TWS", "i99999")
}
}
@@ -1,10 +1,12 @@
package eu.darken.capod.pods.core.apple package eu.darken.capod.pods.core.apple.misc
import android.content.Context import android.content.Context
import eu.darken.capod.R import eu.darken.capod.R
import eu.darken.capod.common.bluetooth.BleScanResult import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.ApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant import java.time.Instant
import javax.inject.Inject import javax.inject.Inject
@@ -28,13 +30,13 @@ data class UnknownAppleDevice(
get() = rssiAverage ?: super.rssi get() = rssiAverage ?: super.rssi
class Factory @Inject constructor() : ApplePodsFactory<ApplePods>(TAG) { class Factory @Inject constructor() : ApplePodsFactory<ApplePods>(TAG) {
override fun isResponsible(proximityMessage: ProximityPairing.Message): Boolean = true override fun isResponsible(message: ProximityPairing.Message): Boolean = true
override fun create( override fun create(
scanResult: BleScanResult, scanResult: BleScanResult,
proximityMessage: ProximityPairing.Message, message: ProximityPairing.Message,
): ApplePods { ): ApplePods {
var basic = UnknownAppleDevice(scanResult = scanResult, proximityMessage = proximityMessage) var basic = UnknownAppleDevice(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic) val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id) if (result != null) basic = basic.copy(identifier = result.id)
@@ -0,0 +1,143 @@
package eu.darken.capod.pods.core.apple.misc
import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.isBitSet
import eu.darken.capod.common.lowerNibble
import eu.darken.capod.common.upperNibble
import eu.darken.capod.pods.core.DualPodDevice
import eu.darken.capod.pods.core.HasCase
import eu.darken.capod.pods.core.HasDualMicrophone
import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.ApplePods
import eu.darken.capod.pods.core.apple.ApplePodsFactory
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import java.time.Instant
import javax.inject.Inject
/**
* AirPods Pro clone similar to Twsi999999.
* Shorter data structure.
*/
data class VarunrAirPodsPro constructor(
override val identifier: PodDevice.Id = PodDevice.Id(),
override val seenLastAt: Instant = Instant.now(),
override val seenFirstAt: Instant = Instant.now(),
override val seenCounter: Int = 1,
override val scanResult: BleScanResult,
override val proximityMessage: ProximityPairing.Message,
override val confidence: Float = PodDevice.BASE_CONFIDENCE,
private val rssiAverage: Int? = null,
private val cachedBatteryPercentage: Float? = null,
) : ApplePods, DualPodDevice, HasDualMicrophone, HasCase {
override val model: PodDevice.Model = PodDevice.Model.VARUNR_AIRPODS_PRO
override val rssi: Int
get() = rssiAverage ?: super<ApplePods>.rssi
/**
* Normally values for the left pod are in the lower nibbles, if the left pod is primary (microphone)
* If the right pod is the primary, the values are flipped.
*/
val areValuesFlipped: Boolean
get() = !rawStatus.isBitSet(5)
override val batteryLeftPodPercent: Float?
get() {
val value = when (areValuesFlipped) {
true -> rawPodsBattery.upperNibble.toInt()
false -> rawPodsBattery.lowerNibble.toInt()
}
return when (value) {
15 -> null
else -> if (value > 10) {
log { "Left pod: Above 100% battery: $value" }
1.0f
} else {
(value / 10f)
}
}
}
override val batteryRightPodPercent: Float?
get() {
val value = when (areValuesFlipped) {
true -> rawPodsBattery.lowerNibble.toInt()
false -> rawPodsBattery.upperNibble.toInt()
}
return when (value) {
15 -> null
else -> if (value > 10) {
log { "Right pod: Above 100% battery: $value" }
1.0f
} else {
value / 10f
}
}
}
val isThisPodInThecase: Boolean
get() = rawStatus.isBitSet(6)
/**
* The data flip bit is set if the left pod is primary.
* For the pod that is in the case, this is flipped again though.
*/
override val isLeftPodMicrophone: Boolean
get() = rawStatus.isBitSet(5) xor isThisPodInThecase
/**
* The data flip bit is UNset if the right pod is primary.
* For the pod that is in the case, this is flipped again though.
*/
override val isRightPodMicrophone: Boolean
get() = !rawStatus.isBitSet(5) xor isThisPodInThecase
override val batteryCasePercent: Float?
get() = when (val value = rawCaseBattery.toInt()) {
15 -> cachedBatteryPercentage
else -> if (value > 10) {
log { "Case: Above 100% battery: $value" }
1.0f
} else {
value / 10f
}
}
override val isCaseCharging: Boolean
get() = rawFlags.isBitSet(2)
class Factory @Inject constructor() : ApplePodsFactory<VarunrAirPodsPro>(TAG) {
override fun isResponsible(message: ProximityPairing.Message): Boolean = message.run {
// Official message length is 19HEX, i.e. binary 25, did they copy this wrong?
getModelInfo().full == DEVICE_CODE && length == 19
}
override fun create(scanResult: BleScanResult, message: ProximityPairing.Message): ApplePods {
var basic = VarunrAirPodsPro(scanResult = scanResult, proximityMessage = message)
val result = searchHistory(basic)
if (result != null) basic = basic.copy(identifier = result.id)
updateHistory(basic)
if (result == null) return basic
return basic.copy(
identifier = result.id,
seenFirstAt = result.seenFirstAt,
seenCounter = result.seenCounter,
confidence = result.confidence,
cachedBatteryPercentage = result.getLatestCaseBattery(),
rssiAverage = result.averageRssi(basic.rssi),
)
}
}
companion object {
private val DEVICE_CODE = 0x0E20.toUShort()
private val TAG = logTag("PodDevice", "Apple", "Varunr", "AirPodsPro")
}
}
@@ -27,10 +27,6 @@ object ProximityPairing {
log { "Not a proximity pairing message: $this" } log { "Not a proximity pairing message: $this" }
return null return null
} }
if (message.length != PROXIMITY_PAIRING_MESSAGE_LENGTH) {
log { "Proximity pairing message has invalid length." }
return null
}
return Message( return Message(
type = message.type, type = message.type,
@@ -43,7 +39,7 @@ object ProximityPairing {
fun getBleScanFilter(): Set<ScanFilter> { fun getBleScanFilter(): Set<ScanFilter> {
val manufacturerData = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply { val manufacturerData = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply {
this[0] = CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING.toByte() this[0] = CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING.toByte()
this[1] = PROXIMITY_PAIRING_MESSAGE_LENGTH.toByte() this[1] = PAIRING_MESSAGE_LENGTH.toByte()
} }
val manufacturerDataMask = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply { val manufacturerDataMask = ByteArray(CONTINUITY_PROTOCOL_MESSAGE_LENGTH).apply {
@@ -62,5 +58,7 @@ object ProximityPairing {
private const val CONTINUITY_PROTOCOL_MESSAGE_LENGTH = 27 private const val CONTINUITY_PROTOCOL_MESSAGE_LENGTH = 27
internal val CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING = 0x07.toUByte() internal val CONTINUITY_PROTOCOL_MESSAGE_TYPE_PROXIMITY_PAIRING = 0x07.toUByte()
internal const val PROXIMITY_PAIRING_MESSAGE_LENGTH = 25
// This is the default message length among official Apple devices, clones may have different length
internal const val PAIRING_MESSAGE_LENGTH = 25
} }
@@ -8,9 +8,9 @@ import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.flow.setupCommonEventHandlers import eu.darken.capod.common.flow.setupCommonEventHandlers
import eu.darken.capod.main.core.GeneralSettings import eu.darken.capod.main.core.GeneralSettings
import eu.darken.capod.monitor.core.PodMonitor import eu.darken.capod.monitor.core.PodMonitor
import eu.darken.capod.pods.core.HasDualEarDetection
import eu.darken.capod.pods.core.HasEarDetection import eu.darken.capod.pods.core.HasEarDetection
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.HasEarDetectionDual
import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.reaction.settings.ReactionSettings import eu.darken.capod.reaction.settings.ReactionSettings
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import javax.inject.Inject import javax.inject.Inject
@@ -68,12 +68,12 @@ class AutoConnect @Inject constructor(
val conditionFulfilled = when (condition) { val conditionFulfilled = when (condition) {
AutoConnectCondition.WHEN_SEEN -> true AutoConnectCondition.WHEN_SEEN -> true
AutoConnectCondition.CASE_OPEN -> when (mainDevice) { AutoConnectCondition.CASE_OPEN -> when (mainDevice) {
is DualApplePods -> mainDevice.caseLidState == DualApplePods.LidState.OPEN is DualAirPods -> mainDevice.caseLidState == DualAirPods.LidState.OPEN
else -> true else -> true
} }
AutoConnectCondition.IN_EAR -> when (mainDevice) { AutoConnectCondition.IN_EAR -> when (mainDevice) {
is HasEarDetection -> { is HasEarDetection -> {
if (mainDevice is HasDualEarDetection && reactionSettings.onePodMode.value) { if (mainDevice is HasEarDetectionDual && reactionSettings.onePodMode.value) {
mainDevice.isEitherPodInEar mainDevice.isEitherPodInEar
} else { } else {
mainDevice.isBeingWorn mainDevice.isBeingWorn
@@ -9,8 +9,8 @@ import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.flow.setupCommonEventHandlers import eu.darken.capod.common.flow.setupCommonEventHandlers
import eu.darken.capod.common.flow.withPrevious import eu.darken.capod.common.flow.withPrevious
import eu.darken.capod.monitor.core.PodMonitor import eu.darken.capod.monitor.core.PodMonitor
import eu.darken.capod.pods.core.HasDualEarDetection
import eu.darken.capod.pods.core.HasEarDetection import eu.darken.capod.pods.core.HasEarDetection
import eu.darken.capod.pods.core.HasEarDetectionDual
import eu.darken.capod.reaction.settings.ReactionSettings import eu.darken.capod.reaction.settings.ReactionSettings
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import javax.inject.Inject import javax.inject.Inject
@@ -48,7 +48,7 @@ class PlayPause @Inject constructor(
return@onEach return@onEach
} }
if (previous is HasDualEarDetection && current is HasDualEarDetection && reactionSettings.onePodMode.value) { if (previous is HasEarDetectionDual && current is HasEarDetectionDual && reactionSettings.onePodMode.value) {
log(TAG) { "Ear status changed for dual pod device in single pod mode." } log(TAG) { "Ear status changed for dual pod device in single pod mode." }
val previousWorn = previous.isEitherPodInEar val previousWorn = previous.isEitherPodInEar
val currentWorn = current.isEitherPodInEar val currentWorn = current.isEitherPodInEar
@@ -8,7 +8,7 @@ import eu.darken.capod.common.flow.setupCommonEventHandlers
import eu.darken.capod.common.flow.withPrevious import eu.darken.capod.common.flow.withPrevious
import eu.darken.capod.monitor.core.PodMonitor import eu.darken.capod.monitor.core.PodMonitor
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.reaction.popup.ui.PopUpWindow import eu.darken.capod.reaction.popup.ui.PopUpWindow
import eu.darken.capod.reaction.settings.ReactionSettings import eu.darken.capod.reaction.settings.ReactionSettings
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@@ -39,7 +39,7 @@ class PopUpReaction @Inject constructor(
.withPrevious() .withPrevious()
.setupCommonEventHandlers(TAG) { "monitor" } .setupCommonEventHandlers(TAG) { "monitor" }
.map { (previous, current) -> .map { (previous, current) ->
if (previous is DualApplePods? && current is DualApplePods) { if (previous is DualAirPods? && current is DualAirPods) {
log(TAG, VERBOSE) { log(TAG, VERBOSE) {
val prev = previous?.rawCaseLidState?.let { String.format("%02X", it.toByte()) } val prev = previous?.rawCaseLidState?.let { String.format("%02X", it.toByte()) }
val cur = current.rawCaseLidState.let { String.format("%02X", it.toByte()) } val cur = current.rawCaseLidState.let { String.format("%02X", it.toByte()) }
@@ -60,8 +60,8 @@ class PopUpReaction @Inject constructor(
} }
} }
private suspend fun tryPopWindow(current: DualApplePods) { private suspend fun tryPopWindow(current: DualAirPods) {
if (current.caseLidState == DualApplePods.LidState.OPEN) { if (current.caseLidState == DualAirPods.LidState.OPEN) {
log(TAG, INFO) { "Show popup" } log(TAG, INFO) { "Show popup" }
val now = Instant.now() val now = Instant.now()
@@ -78,9 +78,9 @@ class PopUpReaction @Inject constructor(
withContext(dispatcherProvider.Main) { withContext(dispatcherProvider.Main) {
popupWindow.show(current) popupWindow.show(current)
} }
} else if (current.caseLidState != DualApplePods.LidState.OPEN) { } else if (current.caseLidState != DualAirPods.LidState.OPEN) {
when (current.caseLidState) { when (current.caseLidState) {
DualApplePods.LidState.CLOSED -> { DualAirPods.LidState.CLOSED -> {
log(TAG, INFO) { "Lid was actively closed, resetting cooldown." } log(TAG, INFO) { "Lid was actively closed, resetting cooldown." }
coolDowns.remove(current.identifier) coolDowns.remove(current.identifier)
} }
@@ -10,11 +10,9 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import eu.darken.capod.R import eu.darken.capod.R
import eu.darken.capod.common.debug.autoreport.DebugSettings import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.databinding.PopupNotificationDualPodsBinding import eu.darken.capod.databinding.PopupNotificationDualPodsBinding
import eu.darken.capod.databinding.PopupNotificationSinglePodsBasicBinding
import eu.darken.capod.databinding.PopupNotificationSinglePodsBinding import eu.darken.capod.databinding.PopupNotificationSinglePodsBinding
import eu.darken.capod.pods.core.* import eu.darken.capod.pods.core.*
import eu.darken.capod.pods.core.apple.BasicSingleApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.DualApplePods
import eu.darken.capod.pods.core.apple.SingleApplePods import eu.darken.capod.pods.core.apple.SingleApplePods
import javax.inject.Inject import javax.inject.Inject
@@ -28,16 +26,13 @@ class PopUpPodViewFactory @Inject constructor(
private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
fun createContentView(parent: ViewGroup, device: PodDevice): View = when (device) { fun createContentView(parent: ViewGroup, device: PodDevice): View = when (device) {
is DualApplePods -> createDualApplePods(parent, device) is DualAirPods -> createDualApplePods(parent, device)
is SingleApplePods -> createSingleApplePods(parent, device) // Unused, has no case to trigger reaction? // Unused, has no case to trigger reaction?
is BasicSingleApplePods -> createSingleBasicApplePods( is SingleApplePods -> createSingleApplePods(parent, device)
parent,
device
) // Unused, has no case to trigger reaction?
else -> throw IllegalArgumentException("Unexpected device: $device") else -> throw IllegalArgumentException("Unexpected device: $device")
} }
private fun createDualApplePods(parent: ViewGroup, device: DualApplePods): View = private fun createDualApplePods(parent: ViewGroup, device: DualAirPods): View =
PopupNotificationDualPodsBinding.inflate(layoutInflater, parent, false).apply { PopupNotificationDualPodsBinding.inflate(layoutInflater, parent, false).apply {
device.apply { device.apply {
podIcon.setImageResource(iconRes) podIcon.setImageResource(iconRes)
@@ -72,17 +67,4 @@ class PopUpPodViewFactory @Inject constructor(
} }
}.root }.root
private fun createSingleBasicApplePods(parent: ViewGroup, device: BasicSingleApplePods): View =
PopupNotificationSinglePodsBasicBinding.inflate(layoutInflater, parent, false).apply {
device.apply {
headphonesIcon.setImageResource(iconRes)
headphonesLabel.text = getLabel(context)
signal.text = getSignalQuality(context)
signal.isInvisible = debugSettings.isDebugModeEnabled.value
headphonesBatteryIcon.setImageResource(getBatteryDrawable(batteryHeadsetPercent))
headphonesBatteryLabel.text = getBatteryLevelHeadset(context)
}
}.root
} }
+1 -1
View File
@@ -22,7 +22,7 @@
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
tools:listitem="@layout/overview_pods_apple_dual_item" tools:listitem="@layout/overview_pods_dual_item"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" /> app:layout_constraintTop_toBottomOf="@id/toolbar" />
@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<TextView
android:id="@+id/headphones_label"
style="@style/TextAppearance.Compat.Notification.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
tools:text="Beats Solo 3" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/headphones_battery_icon"
style="@style/PodInfoItemIcon"
android:src="@drawable/ic_baseline_battery_unknown_24" />
<TextView
android:id="@+id/headphones_battery_label"
style="@style/TextAppearance.Compat.Notification.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
tools:text="100%" />
</LinearLayout>
</LinearLayout>
@@ -1,152 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/card"
style="@style/MyCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
tools:context=".main.ui.MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_content"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/device_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="@id/name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/name"
app:srcCompat="@drawable/ic_device_generic_headphones" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/name"
style="@style/TextAppearance.MaterialComponents.Body2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginStart="4dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:gravity="center_vertical"
app:layout_constraintBottom_toTopOf="@+id/last_seen"
app:layout_constraintEnd_toStartOf="@id/reception"
app:layout_constraintStart_toEndOf="@id/device_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="Power Beats 3" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/last_seen"
style="@style/TextAppearance.MaterialComponents.Caption"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@id/barrier_top"
app:layout_constraintEnd_toEndOf="@id/name"
app:layout_constraintStart_toStartOf="@id/name"
app:layout_constraintTop_toBottomOf="@id/name"
tools:text="3s ago" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/reception"
style="@style/TextAppearance.MaterialComponents.Caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginStart="8dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="@id/name"
app:layout_constraintEnd_toStartOf="@id/reception_icon"
app:layout_constraintStart_toEndOf="@id/name"
app:layout_constraintTop_toTopOf="@+id/name"
tools:text="Yours (RSSI -61)" />
<ImageView
android:id="@+id/reception_icon"
style="@style/TextAppearance.MaterialComponents.Caption"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginHorizontal="16dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="16dp"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="@+id/reception"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/reception"
app:layout_constraintTop_toTopOf="@+id/reception"
app:srcCompat="@drawable/ic_baseline_settings_input_antenna_24"
tools:text="Yours (RSSI -61)" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="headphones"
tools:layout_editor_absoluteY="60dp" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headphones"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier_top"
app:layout_constraintVertical_bias="0.0"
app:layout_goneMarginBottom="16dp">
<ImageView
android:id="@+id/battery_icon"
style="@style/PodInfoItemIcon"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintBottom_toBottomOf="@id/battery_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/battery_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/battery_label"
style="@style/PodInfoItemText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="2dp"
android:text="@string/general_value_not_available_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/battery_icon"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="headphones" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/status"
style="@style/TextAppearance.MaterialComponents.Body2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:gravity="center_vertical"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier_bottom"
tools:text="Music Active, Case Closed" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
@@ -12,7 +12,8 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_content" android:id="@+id/card_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:paddingBottom="16dp">
<ImageView <ImageView
android:id="@+id/device_icon" android:id="@+id/device_icon"
@@ -107,7 +108,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:minHeight="108dp"
app:layout_constraintBottom_toTopOf="@id/barrier_bottom" app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
app:layout_constraintEnd_toStartOf="@id/pod_case_container" app:layout_constraintEnd_toStartOf="@id/pod_case_container"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -117,6 +117,7 @@
<ImageView <ImageView
android:id="@+id/pod_left_icon" android:id="@+id/pod_left_icon"
style="@style/PodInfoItemIcon" style="@style/PodInfoItemIcon"
android:contentDescription="@string/pods_dual_left_label"
android:src="@drawable/ic_airpod_left_24" android:src="@drawable/ic_airpod_left_24"
app:layout_constraintBottom_toBottomOf="@id/pod_left_label" app:layout_constraintBottom_toBottomOf="@id/pod_left_label"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -322,6 +323,7 @@
<ImageView <ImageView
android:id="@+id/pod_right_icon" android:id="@+id/pod_right_icon"
style="@style/PodInfoItemIcon" style="@style/PodInfoItemIcon"
android:contentDescription="@string/pods_dual_right_label"
android:src="@drawable/ic_airpod_right_24" android:src="@drawable/ic_airpod_right_24"
app:layout_constraintBottom_toBottomOf="@id/pod_right_label" app:layout_constraintBottom_toBottomOf="@id/pod_right_label"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -420,7 +422,6 @@
app:layout_constraintTop_toBottomOf="@id/pod_right_microphone_label" /> app:layout_constraintTop_toBottomOf="@id/pod_right_microphone_label" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.Barrier <androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_bottom" android:id="@+id/barrier_bottom"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -435,7 +436,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:gravity="center_vertical" android:gravity="center_vertical"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -12,7 +12,8 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_content" android:id="@+id/card_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:paddingBottom="16dp">
<ImageView <ImageView
android:id="@+id/device_icon" android:id="@+id/device_icon"
@@ -96,13 +97,11 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:minHeight="64dp"
app:layout_constraintBottom_toTopOf="@id/barrier_bottom" app:layout_constraintBottom_toTopOf="@id/barrier_bottom"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/barrier_top" app:layout_constraintTop_toBottomOf="@id/barrier_top"
app:layout_constraintVertical_bias="0.0" app:layout_constraintVertical_bias="0.0">
app:layout_goneMarginBottom="16dp">
<ImageView <ImageView
android:id="@+id/battery_icon" android:id="@+id/battery_icon"
@@ -180,7 +179,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp" android:layout_marginHorizontal="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:gravity="center_vertical" android:gravity="center_vertical"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -1,81 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/headphones_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_device_generic_earbuds"
app:layout_constraintBottom_toBottomOf="@id/headphones_label"
app:layout_constraintEnd_toStartOf="@id/headphones_label"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/headphones_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/headphones_label"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="8dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toStartOf="@id/signal"
app:layout_constraintStart_toEndOf="@id/headphones_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="Beats Solo 3" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/signal"
style="@style/TextAppearance.MaterialComponents.Caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableEnd="@drawable/ic_baseline_signal_cellular_alt_24"
android:gravity="center"
android:minWidth="44dp"
app:layout_constraintBottom_toBottomOf="@+id/headphones_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/headphones_label"
tools:text="-90%" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/headphones_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/headphones_label">
<ImageView
android:id="@id/headphones_battery_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_baseline_battery_unknown_24"
app:layout_constraintBottom_toBottomOf="@id/headphones_battery_label"
app:layout_constraintEnd_toStartOf="@id/headphones_battery_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/headphones_battery_label" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/headphones_battery_label"
style="@style/TextAppearance.MaterialComponents.Body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/headphones_battery_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="100%" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
-6
View File
@@ -81,7 +81,6 @@
<string name="settings_monitor_mode_label">Müşahidə rejimi</string> <string name="settings_monitor_mode_label">Müşahidə rejimi</string>
<string name="settings_monitor_mode_description">Bu tətbiq hansı şərtlər altında Bluetooth verilənlərini müşahidə edir.</string> <string name="settings_monitor_mode_description">Bu tətbiq hansı şərtlər altında Bluetooth verilənlərini müşahidə edir.</string>
<string name="settings_scanner_mode_label">Skaner rejimi</string> <string name="settings_scanner_mode_label">Skaner rejimi</string>
<string name="settings_scanner_mode_description">Bluetooth Zəif Enerji skaneri performansa üstünlük verməlidir, yoxsa enerjiyə qənaət etməlidir?</string>
<string name="settings_monitor_mode_manual_label">Tətbiq açılanda</string> <string name="settings_monitor_mode_manual_label">Tətbiq açılanda</string>
<string name="settings_monitor_mode_automatic_label">Cihazla bağlantı qurulanda</string> <string name="settings_monitor_mode_automatic_label">Cihazla bağlantı qurulanda</string>
<string name="settings_monitor_mode_always_label">Həmişə</string> <string name="settings_monitor_mode_always_label">Həmişə</string>
@@ -89,13 +88,10 @@
<string name="settings_scanner_mode_balanced_label">Tarazlı</string> <string name="settings_scanner_mode_balanced_label">Tarazlı</string>
<string name="settings_scanner_mode_lowlatency_label">Aşağı gecikmə</string> <string name="settings_scanner_mode_lowlatency_label">Aşağı gecikmə</string>
<string name="settings_autopause_label">Avto-fasilə</string> <string name="settings_autopause_label">Avto-fasilə</string>
<string name="settings_autopause_description">Cihazı qulağınızdan çıxaranda musiqiyə fasilə verilsin.</string>
<string name="settings_showall_label">Bütün cihazları göstər</string> <string name="settings_showall_label">Bütün cihazları göstər</string>
<string name="settings_showall_description">Sizə yaxın olan digər insanların cihazlarını göstər.</string> <string name="settings_showall_description">Sizə yaxın olan digər insanların cihazlarını göstər.</string>
<string name="settings_autopplay_label">Avto-oynatma</string> <string name="settings_autopplay_label">Avto-oynatma</string>
<string name="settings_autoplay_description">Cihazı qulağa taxanda musiqini oynat.</string>
<string name="settings_fake_data_label">Saxta verilənlər</string> <string name="settings_fake_data_label">Saxta verilənlər</string>
<string name="settings_fake_data_description">Saxta verilənləri göstər, yəni, mövcud olmayan cihazı simulyasiya edin.</string>
<string name="settings_debug_label">Sazlama tənzimləmələri</string> <string name="settings_debug_label">Sazlama tənzimləmələri</string>
<string name="settings_debug_description">Tətbiqlə əlaqəli problemləri aradan qaldırmağa kömək edəcək əlavə tənzimləmələr.</string> <string name="settings_debug_description">Tətbiqlə əlaqəli problemləri aradan qaldırmağa kömək edəcək əlavə tənzimləmələr.</string>
<string name="settings_signal_minimum_label">Minimum siqnal keyfiyyəti</string> <string name="settings_signal_minimum_label">Minimum siqnal keyfiyyəti</string>
@@ -119,11 +115,9 @@
<string name="upgrade_capod_description">Əlavə özəllikləri əldə edin və tərtibatçını dəstəkləyin.</string> <string name="upgrade_capod_description">Əlavə özəllikləri əldə edin və tərtibatçını dəstəkləyin.</string>
<string name="settings_popup_caseopen_label">Açılan pəncərəni göstər</string> <string name="settings_popup_caseopen_label">Açılan pəncərəni göstər</string>
<string name="settings_popup_caseopen_description">Cihazın qutusu açılanda bir açılan pəncərə göstər (təcrübi).</string> <string name="settings_popup_caseopen_description">Cihazın qutusu açılanda bir açılan pəncərə göstər (təcrübi).</string>
<string name="notification_channel_reaction_popup_label">Açılan cihaz reaksiyaları</string>
<string name="overview_bluetooth_disabled_label">Bluetooth sıradan çıxarıldı</string> <string name="overview_bluetooth_disabled_label">Bluetooth sıradan çıxarıldı</string>
<string name="overview_bluetooth_disabled_description">Bluetooth sıradan çıxarıldı, fəallaşdırın ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth sıradan çıxarıldı, fəallaşdırın ;)</string>
<string name="help_translate_label">Tərcümə</string> <string name="help_translate_label">Tərcümə</string>
<string name="help_translate_description">Bunu sevimli dilinizə tərcümə etməyə kömək edin.</string>
<string name="settings_onepod_mode_label">Tək tərəf rejimi</string> <string name="settings_onepod_mode_label">Tək tərəf rejimi</string>
<string name="settings_onepod_mode_description">Hər iki tərəfi də taxmağa ehtiyac yoxdur, reaksiyaları tətikləmək üçün tək tərəfi taxmaq yetərlidir.</string> <string name="settings_onepod_mode_description">Hər iki tərəfi də taxmağa ehtiyac yoxdur, reaksiyaları tətikləmək üçün tək tərəfi taxmaq yetərlidir.</string>
<string name="permission_system_alert_window_label">Sistem xəbərdarlıq pəncərəsi</string> <string name="permission_system_alert_window_label">Sistem xəbərdarlıq pəncərəsi</string>
+6 -1
View File
@@ -1,2 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="general_done_action">সম্পন্ন</string>
<string name="general_thank_you_label">ধন্যবাদ</string>
<string name="debug_debuglog_size_label">আকার</string>
<string name="settings_general_label">সেটিংস</string>
</resources>
+6 -5
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Mode monitor</string> <string name="settings_monitor_mode_label">Mode monitor</string>
<string name="settings_monitor_mode_description">En quines circumstàncies aquesta aplicació supervisa les dades Bluetooth.</string> <string name="settings_monitor_mode_description">En quines circumstàncies aquesta aplicació supervisa les dades Bluetooth.</string>
<string name="settings_scanner_mode_label">Mode escàner</string> <string name="settings_scanner_mode_label">Mode escàner</string>
<string name="settings_scanner_mode_description">L\'escàner Bluetooth Low Energy hauria de prioritzar el rendiment o estalviar energia?</string> <string name="settings_scanner_mode_description">L\'escàner de dades Bluetooth Low Energy hauria de prioritzar el rendiment o estalviar energia?</string>
<string name="settings_monitor_mode_manual_label">Quan l\'aplicació està oberta</string> <string name="settings_monitor_mode_manual_label">Quan l\'aplicació està oberta</string>
<string name="settings_monitor_mode_automatic_label">Quan el dispositiu està connectat</string> <string name="settings_monitor_mode_automatic_label">Quan el dispositiu està connectat</string>
<string name="settings_monitor_mode_always_label">Sempre</string> <string name="settings_monitor_mode_always_label">Sempre</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Equilibrat</string> <string name="settings_scanner_mode_balanced_label">Equilibrat</string>
<string name="settings_scanner_mode_lowlatency_label">Baixa latència</string> <string name="settings_scanner_mode_lowlatency_label">Baixa latència</string>
<string name="settings_autopause_label">Pausa automàtica</string> <string name="settings_autopause_label">Pausa automàtica</string>
<string name="settings_autopause_description">Pausa la música quan ús tragueu el dispositiu de l\'orella.</string> <string name="settings_autopause_description">Pausa l\'àudio quan ús tragueu el dispositiu de l\'orella.</string>
<string name="settings_showall_label">Mostra tots els dispositius</string> <string name="settings_showall_label">Mostra tots els dispositius</string>
<string name="settings_showall_description">Mostra els dispositius d\'altres persones que estan a prop vostre.</string> <string name="settings_showall_description">Mostra els dispositius d\'altres persones que estan a prop vostre.</string>
<string name="settings_autopplay_label">Reproducció automàtica</string> <string name="settings_autopplay_label">Reproducció automàtica</string>
<string name="settings_autoplay_description">Inicia la reproducció de música quan ús poseu el dispositiu.</string> <string name="settings_autoplay_description">Inicia la reproducció d\'àudio en utilitzar el dispositiu.</string>
<string name="settings_fake_data_label">Dades falses</string> <string name="settings_fake_data_label">Dades falses</string>
<string name="settings_fake_data_description">Mostra dades falses. Per exemple: simula un dispositiu que no existeix.</string> <string name="settings_fake_data_description">Mostra dades falses. Per exemple: simula dispositius que no existeixen.</string>
<string name="settings_debug_label">Configuració de depuració</string> <string name="settings_debug_label">Configuració de depuració</string>
<string name="settings_debug_description">Configuració addicional per ajudar a resoldre problemes amb l\'aplicació.</string> <string name="settings_debug_description">Configuració addicional per ajudar a resoldre problemes amb l\'aplicació.</string>
<string name="settings_signal_minimum_label">Qualitat de senyal mínima</string> <string name="settings_signal_minimum_label">Qualitat de senyal mínima</string>
@@ -119,7 +119,6 @@
<string name="upgrade_capod_description">Obteniu característiques addicionals i doneu suport al desenvolupador.</string> <string name="upgrade_capod_description">Obteniu característiques addicionals i doneu suport al desenvolupador.</string>
<string name="settings_popup_caseopen_label">Mostra la finestra emergent</string> <string name="settings_popup_caseopen_label">Mostra la finestra emergent</string>
<string name="settings_popup_caseopen_description">Mostra una finestra emergent quan s\'obre la funda del dispositiu (experimental).</string> <string name="settings_popup_caseopen_description">Mostra una finestra emergent quan s\'obre la funda del dispositiu (experimental).</string>
<string name="notification_channel_reaction_popup_label">Reaccions emergents del dispositiu</string>
<string name="overview_bluetooth_disabled_label">El Bluetooth està desactivat</string> <string name="overview_bluetooth_disabled_label">El Bluetooth està desactivat</string>
<string name="overview_bluetooth_disabled_description">El Bluetooth està desactivat, activeu-lo ;)</string> <string name="overview_bluetooth_disabled_description">El Bluetooth està desactivat, activeu-lo ;)</string>
<string name="help_translate_label">Traducció</string> <string name="help_translate_label">Traducció</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Dades BLE sense filtrar</string> <string name="settings_blescanner_unfiltered_label">Dades BLE sense filtrar</string>
<string name="settings_blescanner_unfiltered_description">Elimina els filtres de l\'escàner BLE per mostrar totes les dades BLE emeses. Útil per afegir suport a nous tipus d\'auriculars.</string> <string name="settings_blescanner_unfiltered_description">Elimina els filtres de l\'escàner BLE per mostrar totes les dades BLE emeses. Útil per afegir suport a nous tipus d\'auriculars.</string>
<string name="permission_required_title">Cal el permís següent:</string> <string name="permission_required_title">Cal el permís següent:</string>
<string name="settings_compatibility_mode_label">Mode de compatibilitat</string>
<string name="settings_compatibility_mode_description">Desactiva les optimitzacions per millorar la compatibilitat. Proveu això si no veieu cap dada.</string>
</resources> </resources>
+4 -3
View File
@@ -89,11 +89,11 @@
<string name="settings_scanner_mode_balanced_label">Vyvážený</string> <string name="settings_scanner_mode_balanced_label">Vyvážený</string>
<string name="settings_scanner_mode_lowlatency_label">Nízká latence</string> <string name="settings_scanner_mode_lowlatency_label">Nízká latence</string>
<string name="settings_autopause_label">Autom. pozastavení</string> <string name="settings_autopause_label">Autom. pozastavení</string>
<string name="settings_autopause_description">Při vyjmutí zařízení z ucha pozastavit přehrávání hudby.</string> <string name="settings_autopause_description">Pozastavení zvuku při vyjmutí zařízení z ucha.</string>
<string name="settings_showall_label">Zobrazit všechna zařízení</string> <string name="settings_showall_label">Zobrazit všechna zařízení</string>
<string name="settings_showall_description">Zobrazit zařízení ostatních osob, které se nacházejí ve vaší blízkosti.</string> <string name="settings_showall_description">Zobrazit zařízení ostatních osob, které se nacházejí ve vaší blízkosti.</string>
<string name="settings_autopplay_label">Autom. přehrávání</string> <string name="settings_autopplay_label">Autom. přehrávání</string>
<string name="settings_autoplay_description">Spustit přehrávání hudby při použití zařízení.</string> <string name="settings_autoplay_description">Spuštění přehrávání zvuku při nošení zařízení.</string>
<string name="settings_fake_data_label">Falešná data</string> <string name="settings_fake_data_label">Falešná data</string>
<string name="settings_fake_data_description">Zobrazit falešná data např. simulovat zařízení, které neexistuje.</string> <string name="settings_fake_data_description">Zobrazit falešná data např. simulovat zařízení, které neexistuje.</string>
<string name="settings_debug_label">Nastavení ladění</string> <string name="settings_debug_label">Nastavení ladění</string>
@@ -119,7 +119,6 @@
<string name="upgrade_capod_description">Získat další funkce a podpořit vývojáře.</string> <string name="upgrade_capod_description">Získat další funkce a podpořit vývojáře.</string>
<string name="settings_popup_caseopen_label">Zobrazit vyskakovací okno</string> <string name="settings_popup_caseopen_label">Zobrazit vyskakovací okno</string>
<string name="settings_popup_caseopen_description">Zobrazit vyskakovací okno, pokud je pouzdro zařízení otevřeno (experimentální).</string> <string name="settings_popup_caseopen_description">Zobrazit vyskakovací okno, pokud je pouzdro zařízení otevřeno (experimentální).</string>
<string name="notification_channel_reaction_popup_label">Vyskakovací okno reakcí zařízení</string>
<string name="overview_bluetooth_disabled_label">Bluetooth je vypnuto</string> <string name="overview_bluetooth_disabled_label">Bluetooth je vypnuto</string>
<string name="overview_bluetooth_disabled_description">Bluetooth je vypnuto, zapněte jej ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth je vypnuto, zapněte jej ;)</string>
<string name="help_translate_label">Překlad</string> <string name="help_translate_label">Překlad</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Nefiltrovaná data BLE</string> <string name="settings_blescanner_unfiltered_label">Nefiltrovaná data BLE</string>
<string name="settings_blescanner_unfiltered_description">Aby se zobrazovala všechna vysílaná data BLE, odstraňte ze skenování BLE všechny filtry. Užitečné pro přidání podpory nových typů sluchátek.</string> <string name="settings_blescanner_unfiltered_description">Aby se zobrazovala všechna vysílaná data BLE, odstraňte ze skenování BLE všechny filtry. Užitečné pro přidání podpory nových typů sluchátek.</string>
<string name="permission_required_title">Je vyžadováno následující oprávnění:</string> <string name="permission_required_title">Je vyžadováno následující oprávnění:</string>
<string name="settings_compatibility_mode_label">Režim kompatibility</string>
<string name="settings_compatibility_mode_description">Vypnutí optimalizace pro zlepšení kompatibility. Zkuste to, pokud se vám nezobrazují žádná data.</string>
</resources> </resources>
+7 -6
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Überwachungsmodus</string> <string name="settings_monitor_mode_label">Überwachungsmodus</string>
<string name="settings_monitor_mode_description">Unter welchen Umständen überwacht diese App Bluetooth-Daten.</string> <string name="settings_monitor_mode_description">Unter welchen Umständen überwacht diese App Bluetooth-Daten.</string>
<string name="settings_scanner_mode_label">Scannermodus</string> <string name="settings_scanner_mode_label">Scannermodus</string>
<string name="settings_scanner_mode_description">Soll der Bluetooth Low Energie-Scanner Leistung priorisieren oder Energie sparen?</string> <string name="settings_scanner_mode_description">Soll der Bluetooth Low Energy Datenscanner Leistung priorisieren oder Energie sparen?</string>
<string name="settings_monitor_mode_manual_label">Wenn die App geöffnet ist</string> <string name="settings_monitor_mode_manual_label">Wenn die App geöffnet ist</string>
<string name="settings_monitor_mode_automatic_label">Wenn das Gerät verbunden ist</string> <string name="settings_monitor_mode_automatic_label">Wenn das Gerät verbunden ist</string>
<string name="settings_monitor_mode_always_label">Stets</string> <string name="settings_monitor_mode_always_label">Stets</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Ausgewogen</string> <string name="settings_scanner_mode_balanced_label">Ausgewogen</string>
<string name="settings_scanner_mode_lowlatency_label">Geringe Latenz</string> <string name="settings_scanner_mode_lowlatency_label">Geringe Latenz</string>
<string name="settings_autopause_label">Automatische Pause</string> <string name="settings_autopause_label">Automatische Pause</string>
<string name="settings_autopause_description">Halten Sie die Musik an, wenn Sie das Gerät von Ihrem Ohr entfernen.</string> <string name="settings_autopause_description">Halten Sie den Ton an, wenn Sie das Gerät von Ihrem Ohr entfernen.</string>
<string name="settings_showall_label">Alle Geräte anzeigen</string> <string name="settings_showall_label">Alle Geräte anzeigen</string>
<string name="settings_showall_description">Zeigen Sie die Geräte anderer Personen in Ihrer Nähe an.</string> <string name="settings_showall_description">Zeigen Sie die Geräte anderer Personen in Ihrer Nähe an.</string>
<string name="settings_autopplay_label">Automatisches Abspielen</string> <string name="settings_autopplay_label">Automatisches Abspielen</string>
<string name="settings_autoplay_description">Starten Sie die Musikwiedergabe, wenn Sie das Gerät tragen.</string> <string name="settings_autoplay_description">Starten Sie die Audiowiedergabe, wenn das Gerät getragen wird.</string>
<string name="settings_fake_data_label">Gefälschte Daten</string> <string name="settings_fake_data_label">Gefälschte Daten</string>
<string name="settings_fake_data_description">Gefälschte Daten anzeigen, Geräte simulieren, die nicht existieren.</string> <string name="settings_fake_data_description">Falsche Daten anzeigen, also nicht existierende Geräte simulieren.</string>
<string name="settings_debug_label">Debug-Einstellungen</string> <string name="settings_debug_label">Debug-Einstellungen</string>
<string name="settings_debug_description">Zusätzliche Einstellungen zur Behebung von Problemen mit der App.</string> <string name="settings_debug_description">Zusätzliche Einstellungen zur Behebung von Problemen mit der App.</string>
<string name="settings_signal_minimum_label">Minimale Signalqualität</string> <string name="settings_signal_minimum_label">Minimale Signalqualität</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Erhalten Sie zusätzliche Funktionen und unterstützen Sie den Entwickler.</string> <string name="upgrade_capod_description">Erhalten Sie zusätzliche Funktionen und unterstützen Sie den Entwickler.</string>
<string name="settings_popup_caseopen_label">Popup zeigen</string> <string name="settings_popup_caseopen_label">Popup zeigen</string>
<string name="settings_popup_caseopen_description">Ein Popup anzeigen, wenn das Gerätegehäuse geöffnet wird (experimentell).</string> <string name="settings_popup_caseopen_description">Ein Popup anzeigen, wenn das Gerätegehäuse geöffnet wird (experimentell).</string>
<string name="notification_channel_reaction_popup_label">Popup-Gerätereaktionen</string>
<string name="overview_bluetooth_disabled_label">Bluetooth ist deaktiviert</string> <string name="overview_bluetooth_disabled_label">Bluetooth ist deaktiviert</string>
<string name="overview_bluetooth_disabled_description">Bluetooth ist deaktiviert, aktiviere es ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth ist deaktiviert, aktiviere es ;)</string>
<string name="help_translate_label">Übersetzung</string> <string name="help_translate_label">Übersetzung</string>
<string name="help_translate_description">Helfen Sie mit, dies in Ihre Lieblingssprache zu übersetzen.</string> <string name="help_translate_description">Helfen Sie mit, diese App in Ihre Lieblingssprache zu übersetzen.</string>
<string name="settings_onepod_mode_label">Ein-Pod-Modus</string> <string name="settings_onepod_mode_label">Ein-Pod-Modus</string>
<string name="settings_onepod_mode_description">Das Tragen beider Pods ist nicht erforderlich, das Tragen eines einzigen Pods reicht aus, um Reaktionen auszulösen.</string> <string name="settings_onepod_mode_description">Das Tragen beider Pods ist nicht erforderlich, das Tragen eines einzigen Pods reicht aus, um Reaktionen auszulösen.</string>
<string name="permission_system_alert_window_label">Systemwarnungsfenster</string> <string name="permission_system_alert_window_label">Systemwarnungsfenster</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Ungefilterte BLE-Daten</string> <string name="settings_blescanner_unfiltered_label">Ungefilterte BLE-Daten</string>
<string name="settings_blescanner_unfiltered_description">Entfernen Sie alle Filter aus dem BLE-Scanner, um alle übertragenen BLE-Daten anzuzeigen. Nützlich, um Unterstützung für neue Kopfhörertypen hinzuzufügen.</string> <string name="settings_blescanner_unfiltered_description">Entfernen Sie alle Filter aus dem BLE-Scanner, um alle übertragenen BLE-Daten anzuzeigen. Nützlich, um Unterstützung für neue Kopfhörertypen hinzuzufügen.</string>
<string name="permission_required_title">Die folgende Genehmigung ist erforderlich:</string> <string name="permission_required_title">Die folgende Genehmigung ist erforderlich:</string>
<string name="settings_compatibility_mode_label">Kompatibilitätsmodus</string>
<string name="settings_compatibility_mode_description">Deaktivieren Sie Optimierungen, um die Kompatibilität zu verbessern. Versuchen Sie dies, wenn Sie keine Daten sehen.</string>
</resources> </resources>
+8 -7
View File
@@ -37,7 +37,7 @@
<string name="pods_case_status_open_label">Ανοιχτή</string> <string name="pods_case_status_open_label">Ανοιχτή</string>
<string name="pods_case_status_closed_label">Κλειστή</string> <string name="pods_case_status_closed_label">Κλειστή</string>
<string name="pods_connection_state_disconnected_label">Δεν είναι συνδεδεμένο σε συσκευή</string> <string name="pods_connection_state_disconnected_label">Δεν είναι συνδεδεμένο σε συσκευή</string>
<string name="pods_connection_state_idle_label">Συνδεδεμένο σε κάποια συσκευή, αλλά αδρανές</string> <string name="pods_connection_state_idle_label">Συνδεδεμένο σε συσκευή, αλλά αδρανές</string>
<string name="pods_connection_state_music_label">Σε λειτουργία μουσικής</string> <string name="pods_connection_state_music_label">Σε λειτουργία μουσικής</string>
<string name="pods_connection_state_call_label">Σε λειτουργία κλήσης</string> <string name="pods_connection_state_call_label">Σε λειτουργία κλήσης</string>
<string name="pods_connection_state_ringing_label">Κουδούνισμα</string> <string name="pods_connection_state_ringing_label">Κουδούνισμα</string>
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Λειτουργία παρακολούθησης</string> <string name="settings_monitor_mode_label">Λειτουργία παρακολούθησης</string>
<string name="settings_monitor_mode_description">Κάτω από ποιες συνθήκες αυτή η εφαρμογή παρακολουθεί τα δεδομένα Bluetooth.</string> <string name="settings_monitor_mode_description">Κάτω από ποιες συνθήκες αυτή η εφαρμογή παρακολουθεί τα δεδομένα Bluetooth.</string>
<string name="settings_scanner_mode_label">Λειτουργία σάρωσης</string> <string name="settings_scanner_mode_label">Λειτουργία σάρωσης</string>
<string name="settings_scanner_mode_description">Ο σαρωτής Bluetooth Low Energy να δώσει προτεραιότητα στην απόδοση ή στη διατήρηση ενέργειας;</string> <string name="settings_scanner_mode_description">Θα πρέπει η σάρωση δεδομένων χαμηλής ενέργειας Bluetooth να δίνει προτεραιότητα στην απόδοση ή να εξοικονομεί ενέργεια;</string>
<string name="settings_monitor_mode_manual_label">Όταν η εφαρμογή είναι ανοιχτή</string> <string name="settings_monitor_mode_manual_label">Όταν η εφαρμογή είναι ανοιχτή</string>
<string name="settings_monitor_mode_automatic_label">Όταν η συσκευή είναι συνδεδεμένη</string> <string name="settings_monitor_mode_automatic_label">Όταν η συσκευή είναι συνδεδεμένη</string>
<string name="settings_monitor_mode_always_label">Πάντα</string> <string name="settings_monitor_mode_always_label">Πάντα</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Εξισορρόπηση</string> <string name="settings_scanner_mode_balanced_label">Εξισορρόπηση</string>
<string name="settings_scanner_mode_lowlatency_label">Χαμηλή καθυστέρηση</string> <string name="settings_scanner_mode_lowlatency_label">Χαμηλή καθυστέρηση</string>
<string name="settings_autopause_label">Αυτόματη παύση</string> <string name="settings_autopause_label">Αυτόματη παύση</string>
<string name="settings_autopause_description">Παύση μουσικής όταν αφαιρείται τη συσκευή από το αυτί σας.</string> <string name="settings_autopause_description">Παύση ήχου όταν αφαιρείται τη συσκευή από το αυτί σας.</string>
<string name="settings_showall_label">Εμφάνιση όλων των συσκευών</string> <string name="settings_showall_label">Εμφάνιση όλων των συσκευών</string>
<string name="settings_showall_description">Εμφάνιση συσκευών άλλων ανθρώπων που είναι κοντά σας.</string> <string name="settings_showall_description">Εμφάνιση συσκευών άλλων ανθρώπων που είναι κοντά σας.</string>
<string name="settings_autopplay_label">Αυτόματη αναπαραγωγή</string> <string name="settings_autopplay_label">Αυτόματη αναπαραγωγή</string>
<string name="settings_autoplay_description">Αναπαραγωγή μουσικής όταν φοριέται η συσκευή.</string> <string name="settings_autoplay_description">Έναρξη αναπαραγωγής ήχου όταν φορεθεί η συσκευή.</string>
<string name="settings_fake_data_label">Ψευδή δεδομένα</string> <string name="settings_fake_data_label">Ψευδή δεδομένα</string>
<string name="settings_fake_data_description">Εμφάνιση ψευδών δεδομένων, π.χ. προσομοίωση συσκευής που δεν υπάρχει.</string> <string name="settings_fake_data_description">Εμφάνιση ψευδών δεδομένων, π.χ., προσομοίωση συσκευών που δεν υπάρχουν.</string>
<string name="settings_debug_label">Ρυθμίσεις αντιμετώπισης σφαλμάτων</string> <string name="settings_debug_label">Ρυθμίσεις αντιμετώπισης σφαλμάτων</string>
<string name="settings_debug_description">Πρόσθετες ρυθμίσεις που βοηθούν στην αντιμετώπιση προβλημάτων με την εφαρμογή.</string> <string name="settings_debug_description">Πρόσθετες ρυθμίσεις που βοηθούν στην αντιμετώπιση προβλημάτων με την εφαρμογή.</string>
<string name="settings_signal_minimum_label">Ελάχιστη ποιότητα σήματος</string> <string name="settings_signal_minimum_label">Ελάχιστη ποιότητα σήματος</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Λάβετε επιπλέον λειτουργίες και υποστηρίξτε τον προγραμματιστή.</string> <string name="upgrade_capod_description">Λάβετε επιπλέον λειτουργίες και υποστηρίξτε τον προγραμματιστή.</string>
<string name="settings_popup_caseopen_label">Εμφάνιση αναδυόμενου</string> <string name="settings_popup_caseopen_label">Εμφάνιση αναδυόμενου</string>
<string name="settings_popup_caseopen_description">Εμφάνιση αναδυόμενου όταν η θήκη της συσκευής είναι ανοιχτή (πειραματικό).</string> <string name="settings_popup_caseopen_description">Εμφάνιση αναδυόμενου όταν η θήκη της συσκευής είναι ανοιχτή (πειραματικό).</string>
<string name="notification_channel_reaction_popup_label">Αναδυόμενες αντιδράσεις συσκευών</string>
<string name="overview_bluetooth_disabled_label">Το Bluetooth είναι απενεργοποιημένο</string> <string name="overview_bluetooth_disabled_label">Το Bluetooth είναι απενεργοποιημένο</string>
<string name="overview_bluetooth_disabled_description">Το Bluetooth είναι απενεργοποιημένο, ενεργοποιήστε το ;)</string> <string name="overview_bluetooth_disabled_description">Το Bluetooth είναι απενεργοποιημένο, ενεργοποιήστε το ;)</string>
<string name="help_translate_label">Μετάφραση</string> <string name="help_translate_label">Μετάφραση</string>
<string name="help_translate_description">Βοηθήστε να μεταφραστεί στην αγαπημένη σας γλώσσα.</string> <string name="help_translate_description">Βοηθήστε να μεταφραστεί αυτή η εφαρμογή στην αγαπημένη σας γλώσσα.</string>
<string name="settings_onepod_mode_label">Λειτουργία ενός pod</string> <string name="settings_onepod_mode_label">Λειτουργία ενός pod</string>
<string name="settings_onepod_mode_description">Δεν απαιτείται να φοράτε και τα δύο pods, αρκεί να φοράτε ένα μόνο pod για να ενεργοποιούνται αντιδράσεις.</string> <string name="settings_onepod_mode_description">Δεν απαιτείται να φοράτε και τα δύο pods, αρκεί να φοράτε ένα μόνο pod για να ενεργοποιούνται αντιδράσεις.</string>
<string name="permission_system_alert_window_label">Παράθυρο ειδοποίησης συστήματος</string> <string name="permission_system_alert_window_label">Παράθυρο ειδοποίησης συστήματος</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Μη φιλτραρισμένα δεδομένα BLE</string> <string name="settings_blescanner_unfiltered_label">Μη φιλτραρισμένα δεδομένα BLE</string>
<string name="settings_blescanner_unfiltered_description">Αφαιρέστε τυχόν φίλτρα από τη σάρωση BLE για να εμφανίσετε όλα τα δεδομένα BLE που μεταδίδονται. Χρήσιμο για την προσθήκη υποστήριξης για νέους τύπους ακουστικών.</string> <string name="settings_blescanner_unfiltered_description">Αφαιρέστε τυχόν φίλτρα από τη σάρωση BLE για να εμφανίσετε όλα τα δεδομένα BLE που μεταδίδονται. Χρήσιμο για την προσθήκη υποστήριξης για νέους τύπους ακουστικών.</string>
<string name="permission_required_title">Η ακόλουθη άδεια είναι απαραίτητη:</string> <string name="permission_required_title">Η ακόλουθη άδεια είναι απαραίτητη:</string>
<string name="settings_compatibility_mode_label">Λειτουργία συμβατότητας</string>
<string name="settings_compatibility_mode_description">Απενεργοποίηση βελτιστοποιήσεων για βελτίωση συμβατότητας. Δοκιμάστε αυτό εάν δε βλέπετε δεδομένα.</string>
</resources> </resources>
+6 -5
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Modo monitor</string> <string name="settings_monitor_mode_label">Modo monitor</string>
<string name="settings_monitor_mode_description">Bajo qué circunstancias esta aplicación monitorea los datos Bluetooth.</string> <string name="settings_monitor_mode_description">Bajo qué circunstancias esta aplicación monitorea los datos Bluetooth.</string>
<string name="settings_scanner_mode_label">Modo escáner</string> <string name="settings_scanner_mode_label">Modo escáner</string>
<string name="settings_scanner_mode_description">¿El escáner Bluetooth Low Energy debe priorizar el rendimiento o ahorrar energía?</string> <string name="settings_scanner_mode_description">¿El escáner de datos Bluetooth Low Energy debe priorizar el rendimiento o ahorrar energía?</string>
<string name="settings_monitor_mode_manual_label">Cuando la aplicación está abierta</string> <string name="settings_monitor_mode_manual_label">Cuando la aplicación está abierta</string>
<string name="settings_monitor_mode_automatic_label">Cuando el dispositivo está conectado</string> <string name="settings_monitor_mode_automatic_label">Cuando el dispositivo está conectado</string>
<string name="settings_monitor_mode_always_label">Siempre</string> <string name="settings_monitor_mode_always_label">Siempre</string>
@@ -89,11 +89,11 @@
<string name="settings_scanner_mode_balanced_label">Balanceado</string> <string name="settings_scanner_mode_balanced_label">Balanceado</string>
<string name="settings_scanner_mode_lowlatency_label">Baja latencia</string> <string name="settings_scanner_mode_lowlatency_label">Baja latencia</string>
<string name="settings_autopause_label">Pausar automáticamente</string> <string name="settings_autopause_label">Pausar automáticamente</string>
<string name="settings_autopause_description">Pausa la música cuando se quites el dispositivo de la oreja.</string> <string name="settings_autopause_description">Pausa el audio cuando te quites el dispositivo de la oreja.</string>
<string name="settings_showall_label">Mostrar todos los dispositivos</string> <string name="settings_showall_label">Mostrar todos los dispositivos</string>
<string name="settings_showall_description">Muestra los dispositivos de otras personas que están cerca de ti.</string> <string name="settings_showall_description">Muestra los dispositivos de otras personas que están cerca de ti.</string>
<string name="settings_autopplay_label">Reproducción automática</string> <string name="settings_autopplay_label">Reproducción automática</string>
<string name="settings_autoplay_description">Iniciar la reproducción de música cuando use el dispositivo.</string> <string name="settings_autoplay_description">Inicia la reproducción de audio cuando se use el dispositivo.</string>
<string name="settings_fake_data_label">Información falsa</string> <string name="settings_fake_data_label">Información falsa</string>
<string name="settings_fake_data_description">Mostrar datos falsos. Por ejemplo: simular un dispositivo que no existe.</string> <string name="settings_fake_data_description">Mostrar datos falsos. Por ejemplo: simular un dispositivo que no existe.</string>
<string name="settings_debug_label">Configuración de depuración</string> <string name="settings_debug_label">Configuración de depuración</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Obtenga funciones adicionales y apoye al desarrollador.</string> <string name="upgrade_capod_description">Obtenga funciones adicionales y apoye al desarrollador.</string>
<string name="settings_popup_caseopen_label">Mostrar ventanas emergentes</string> <string name="settings_popup_caseopen_label">Mostrar ventanas emergentes</string>
<string name="settings_popup_caseopen_description">Muestra una ventana emergente cuando se abre el estuche del dispositivo (experimental).</string> <string name="settings_popup_caseopen_description">Muestra una ventana emergente cuando se abre el estuche del dispositivo (experimental).</string>
<string name="notification_channel_reaction_popup_label">Reacciones emergentes de dispositivos</string>
<string name="overview_bluetooth_disabled_label">Bluetooth deshabilitado</string> <string name="overview_bluetooth_disabled_label">Bluetooth deshabilitado</string>
<string name="overview_bluetooth_disabled_description">El Bluetooth está deshabilitado, habilítelo ;)</string> <string name="overview_bluetooth_disabled_description">El Bluetooth está deshabilitado, habilítelo ;)</string>
<string name="help_translate_label">Traducción</string> <string name="help_translate_label">Traducción</string>
<string name="help_translate_description">Ayude a traducir esta aplicación a su idioma favorito.</string> <string name="help_translate_description">Ayuda a traducir esta aplicación a tu idioma favorito.</string>
<string name="settings_onepod_mode_label">Modo un audífono</string> <string name="settings_onepod_mode_label">Modo un audífono</string>
<string name="settings_onepod_mode_description">No es necesario usar ambos AirPods, usar un solo AirPod es suficiente para desencadenar reacciones.</string> <string name="settings_onepod_mode_description">No es necesario usar ambos AirPods, usar un solo AirPod es suficiente para desencadenar reacciones.</string>
<string name="permission_system_alert_window_label">Ventana de alerta del sistema</string> <string name="permission_system_alert_window_label">Ventana de alerta del sistema</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Datos BLE sin filtrar</string> <string name="settings_blescanner_unfiltered_label">Datos BLE sin filtrar</string>
<string name="settings_blescanner_unfiltered_description">Elimina los filtros del escáner BLE para mostrar todos los datos BLE transmitidos. Útil para agregar soporte para nuevos tipos de auriculares.</string> <string name="settings_blescanner_unfiltered_description">Elimina los filtros del escáner BLE para mostrar todos los datos BLE transmitidos. Útil para agregar soporte para nuevos tipos de auriculares.</string>
<string name="permission_required_title">Se requiere el siguiente permiso:</string> <string name="permission_required_title">Se requiere el siguiente permiso:</string>
<string name="settings_compatibility_mode_label">Modo de compatibilidad</string>
<string name="settings_compatibility_mode_description">Deshabilita las optimizaciones para mejorar la compatibilidad. Prueba esto si no ves ningún dato.</string>
</resources> </resources>
+6 -5
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Mode surveillance</string> <string name="settings_monitor_mode_label">Mode surveillance</string>
<string name="settings_monitor_mode_description">Les circonstances de surveillance des données Bluetooth par lappli.</string> <string name="settings_monitor_mode_description">Les circonstances de surveillance des données Bluetooth par lappli.</string>
<string name="settings_scanner_mode_label">Mode analyse</string> <string name="settings_scanner_mode_label">Mode analyse</string>
<string name="settings_scanner_mode_description">Le mode analyse des données « basse énergie » de Bluetooth devrait-il prioriser les performances ou préserver l’énergie?</string> <string name="settings_scanner_mode_description">Lanalyseur des données « basse énergie » de Bluetooth devrait-il prioriser les performances ou préserver l’énergie?</string>
<string name="settings_monitor_mode_manual_label">Si lappli est en fonction</string> <string name="settings_monitor_mode_manual_label">Si lappli est en fonction</string>
<string name="settings_monitor_mode_automatic_label">Si lappareil est connecté</string> <string name="settings_monitor_mode_automatic_label">Si lappareil est connecté</string>
<string name="settings_monitor_mode_always_label">Toujours</string> <string name="settings_monitor_mode_always_label">Toujours</string>
@@ -93,9 +93,9 @@
<string name="settings_showall_label">Afficher tous les appareils</string> <string name="settings_showall_label">Afficher tous les appareils</string>
<string name="settings_showall_description">Afficher les appareils dautres personnes à proximité.</string> <string name="settings_showall_description">Afficher les appareils dautres personnes à proximité.</string>
<string name="settings_autopplay_label">Lecture automatique</string> <string name="settings_autopplay_label">Lecture automatique</string>
<string name="settings_autoplay_description">Lire le contenu audio si lappareil est porté.</string> <string name="settings_autoplay_description">Démarrer la lecture du son quand lappareil est porté.</string>
<string name="settings_fake_data_label">Fausses données</string> <string name="settings_fake_data_label">Fausses données</string>
<string name="settings_fake_data_description">Afficher les fausses données, c.-à-d. simuler un appareil qui nexiste pas.</string> <string name="settings_fake_data_description">Afficher les fausses données, c.-à-d. simuler les appareils qui nexistent pas.</string>
<string name="settings_debug_label">Paramètres de débogage</string> <string name="settings_debug_label">Paramètres de débogage</string>
<string name="settings_debug_description">Autres paramètres pour aider à diagnostiquer les problèmes de lappli.</string> <string name="settings_debug_description">Autres paramètres pour aider à diagnostiquer les problèmes de lappli.</string>
<string name="settings_signal_minimum_label">Qualité minimale du signal</string> <string name="settings_signal_minimum_label">Qualité minimale du signal</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Obtenez des fonctions supplémentaires et soutenez le développeur.</string> <string name="upgrade_capod_description">Obtenez des fonctions supplémentaires et soutenez le développeur.</string>
<string name="settings_popup_caseopen_label">Afficher une notification</string> <string name="settings_popup_caseopen_label">Afficher une notification</string>
<string name="settings_popup_caseopen_description">Afficher une notification à louverture de l’étui de l\'appareil (expérimental).</string> <string name="settings_popup_caseopen_description">Afficher une notification à louverture de l’étui de l\'appareil (expérimental).</string>
<string name="notification_channel_reaction_popup_label">Afficher les réactions de lappareil</string>
<string name="overview_bluetooth_disabled_label">Le Bluetooth est désactivé</string> <string name="overview_bluetooth_disabled_label">Le Bluetooth est désactivé</string>
<string name="overview_bluetooth_disabled_description">Le Bluetooth est désactivé, activez-le ;)</string> <string name="overview_bluetooth_disabled_description">Le Bluetooth est désactivé, activez-le ;)</string>
<string name="help_translate_label">Traduction</string> <string name="help_translate_label">Traduction</string>
<string name="help_translate_description">Aidez à traduire lappli dans votre langue préférée.</string> <string name="help_translate_description">Aider à traduire cette appli dans votre langue préférée.</string>
<string name="settings_onepod_mode_label">Mode à un seul AirPod</string> <string name="settings_onepod_mode_label">Mode à un seul AirPod</string>
<string name="settings_onepod_mode_description">Il nest pas nécessaire de porter deux AirPods, en porter un seul suffit à déclencher les réactions.</string> <string name="settings_onepod_mode_description">Il nest pas nécessaire de porter deux AirPods, en porter un seul suffit à déclencher les réactions.</string>
<string name="permission_system_alert_window_label">Fenêtre dalerte système</string> <string name="permission_system_alert_window_label">Fenêtre dalerte système</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Données BÉB non filtrées</string> <string name="settings_blescanner_unfiltered_label">Données BÉB non filtrées</string>
<string name="settings_blescanner_unfiltered_description">Supprimer tous les filtres de lanalyseur BÉB pour afficher toutes les données BÉB diffusées. Utile pour prendre en charge les nouveaux types de casques-micros.</string> <string name="settings_blescanner_unfiltered_description">Supprimer tous les filtres de lanalyseur BÉB pour afficher toutes les données BÉB diffusées. Utile pour prendre en charge les nouveaux types de casques-micros.</string>
<string name="permission_required_title">Lautorisation suivante est nécessaire :</string> <string name="permission_required_title">Lautorisation suivante est nécessaire :</string>
<string name="settings_compatibility_mode_label">Mode de compatibilité</string>
<string name="settings_compatibility_mode_description">Désactiver les optimisations pour améliorer la compatibilité. À essayer si vous ne voyez aucune donnée.</string>
</resources> </resources>
-6
View File
@@ -81,7 +81,6 @@
<string name="settings_monitor_mode_label">Monitor mód</string> <string name="settings_monitor_mode_label">Monitor mód</string>
<string name="settings_monitor_mode_description">Milyen körülmények között figyeli ez az alkalmazás a Bluetooth-adatokat.</string> <string name="settings_monitor_mode_description">Milyen körülmények között figyeli ez az alkalmazás a Bluetooth-adatokat.</string>
<string name="settings_scanner_mode_label">Szkenner mód</string> <string name="settings_scanner_mode_label">Szkenner mód</string>
<string name="settings_scanner_mode_description">A \"Bluetooth alacsony töltöttség\" a szkennernek a teljesítményt kell előnyben részesítenie, vagy energiát takaríthat meg?</string>
<string name="settings_monitor_mode_manual_label">Amikor az alkalmazás nyitva van</string> <string name="settings_monitor_mode_manual_label">Amikor az alkalmazás nyitva van</string>
<string name="settings_monitor_mode_automatic_label">Amikor az eszköz csatlakoztatva van</string> <string name="settings_monitor_mode_automatic_label">Amikor az eszköz csatlakoztatva van</string>
<string name="settings_monitor_mode_always_label">Mindig</string> <string name="settings_monitor_mode_always_label">Mindig</string>
@@ -89,13 +88,10 @@
<string name="settings_scanner_mode_balanced_label">Kiegyensúlyozott</string> <string name="settings_scanner_mode_balanced_label">Kiegyensúlyozott</string>
<string name="settings_scanner_mode_lowlatency_label">Alacsony késleltetés</string> <string name="settings_scanner_mode_lowlatency_label">Alacsony késleltetés</string>
<string name="settings_autopause_label">Automatikus megszakítás</string> <string name="settings_autopause_label">Automatikus megszakítás</string>
<string name="settings_autopause_description">A zene szüneteltetése, amikor eltávolítja a készüléket a füléről.</string>
<string name="settings_showall_label">Az összes eszköz megjelenítése</string> <string name="settings_showall_label">Az összes eszköz megjelenítése</string>
<string name="settings_showall_description">Mutassa meg másoknak az Ön közelében lévő eszközeit.</string> <string name="settings_showall_description">Mutassa meg másoknak az Ön közelében lévő eszközeit.</string>
<string name="settings_autopplay_label">Automatikus lejátszás</string> <string name="settings_autopplay_label">Automatikus lejátszás</string>
<string name="settings_autoplay_description">Indítsa el a zenelejátszást a készülék használatakor.</string>
<string name="settings_fake_data_label">Hamis adat</string> <string name="settings_fake_data_label">Hamis adat</string>
<string name="settings_fake_data_description">Hamis adatok megjelenítése, azaz olyan eszköz szimulálása, amely nem létezik.</string>
<string name="settings_debug_label">Hibakeresési beállítások</string> <string name="settings_debug_label">Hibakeresési beállítások</string>
<string name="settings_debug_description">További beállítások az alkalmazással kapcsolatos problémák megoldásához.</string> <string name="settings_debug_description">További beállítások az alkalmazással kapcsolatos problémák megoldásához.</string>
<string name="settings_signal_minimum_label">Minimális jelerősség</string> <string name="settings_signal_minimum_label">Minimális jelerősség</string>
@@ -119,11 +115,9 @@
<string name="upgrade_capod_description">Szerezzen be további funkciókat és támogassa a fejlesztőt.</string> <string name="upgrade_capod_description">Szerezzen be további funkciókat és támogassa a fejlesztőt.</string>
<string name="settings_popup_caseopen_label">Előugró ablak megjelenítése</string> <string name="settings_popup_caseopen_label">Előugró ablak megjelenítése</string>
<string name="settings_popup_caseopen_description">Egy előugró ablak megjelenítése az eszköz házának kinyitásakor (kísérleti).</string> <string name="settings_popup_caseopen_description">Egy előugró ablak megjelenítése az eszköz házának kinyitásakor (kísérleti).</string>
<string name="notification_channel_reaction_popup_label">Előugró eszköz reakciói</string>
<string name="overview_bluetooth_disabled_label">A Bluetooth kikapcsolva</string> <string name="overview_bluetooth_disabled_label">A Bluetooth kikapcsolva</string>
<string name="overview_bluetooth_disabled_description">Bluetooth kikapcsolva, engedélyezd ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth kikapcsolva, engedélyezd ;)</string>
<string name="help_translate_label">Fordítás</string> <string name="help_translate_label">Fordítás</string>
<string name="help_translate_description">Segíts lefordítani a nyelvedre.</string>
<string name="settings_onepod_mode_label">Egy fülhallgató mód</string> <string name="settings_onepod_mode_label">Egy fülhallgató mód</string>
<string name="settings_onepod_mode_description">Nem szükséges mindkét fülhallgató viselése, elég egy, a működéshez.</string> <string name="settings_onepod_mode_description">Nem szükséges mindkét fülhallgató viselése, elég egy, a működéshez.</string>
<string name="permission_system_alert_window_label">Rendszer figyelmeztető ablak</string> <string name="permission_system_alert_window_label">Rendszer figyelmeztető ablak</string>
+7 -6
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Mode monitor</string> <string name="settings_monitor_mode_label">Mode monitor</string>
<string name="settings_monitor_mode_description">Dalam keadaan apa aplikasi ini memonitor data Bluetooth.</string> <string name="settings_monitor_mode_description">Dalam keadaan apa aplikasi ini memonitor data Bluetooth.</string>
<string name="settings_scanner_mode_label">Modus memindai</string> <string name="settings_scanner_mode_label">Modus memindai</string>
<string name="settings_scanner_mode_description">Haruskah pemindai Bluetooth Hemat Energi memprioritaskan kinerja atau menghemat energi?</string> <string name="settings_scanner_mode_description">Haruskah pemindai data Bluetooth Hemat Energi memprioritaskan kinerja atau menghemat energi?</string>
<string name="settings_monitor_mode_manual_label">Saat aplikasi terbuka</string> <string name="settings_monitor_mode_manual_label">Saat aplikasi terbuka</string>
<string name="settings_monitor_mode_automatic_label">Saat perangkat terhubung</string> <string name="settings_monitor_mode_automatic_label">Saat perangkat terhubung</string>
<string name="settings_monitor_mode_always_label">Selalu</string> <string name="settings_monitor_mode_always_label">Selalu</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Seimbang</string> <string name="settings_scanner_mode_balanced_label">Seimbang</string>
<string name="settings_scanner_mode_lowlatency_label">Latemsi rendah</string> <string name="settings_scanner_mode_lowlatency_label">Latemsi rendah</string>
<string name="settings_autopause_label">Jeda otomatis</string> <string name="settings_autopause_label">Jeda otomatis</string>
<string name="settings_autopause_description">Jeda musik saat melepaskan perangkat dari telinga anda.</string> <string name="settings_autopause_description">Jeda audio saat melepaskan perangkat dari telinga anda.</string>
<string name="settings_showall_label">Tampilkan semua perangkat</string> <string name="settings_showall_label">Tampilkan semua perangkat</string>
<string name="settings_showall_description">Tampilkan perangkat orang lain yang ada di dekat anda.</string> <string name="settings_showall_description">Tampilkan perangkat orang lain yang ada di dekat anda.</string>
<string name="settings_autopplay_label">Putar otomatis</string> <string name="settings_autopplay_label">Putar otomatis</string>
<string name="settings_autoplay_description">Mulai pemutaran musik musik saat memakai perangkat.</string> <string name="settings_autoplay_description">Mulai pemutaran audio saat perangkat dipakai.</string>
<string name="settings_fake_data_label">Data palsu</string> <string name="settings_fake_data_label">Data palsu</string>
<string name="settings_fake_data_description">Tampilkan data palsu, mis: mensimulasikan perangkat yang tidak ada.</string> <string name="settings_fake_data_description">Tampilkan data palsu, yaitu, mensimulasikan perangkat yang tidak ada.</string>
<string name="settings_debug_label">Pengaturan debug</string> <string name="settings_debug_label">Pengaturan debug</string>
<string name="settings_debug_description">Pengaturan tambahan untuk membantu memecahkan masalah dengan aplikasi.</string> <string name="settings_debug_description">Pengaturan tambahan untuk membantu memecahkan masalah dengan aplikasi.</string>
<string name="settings_signal_minimum_label">Kualitas sinyal minimum</string> <string name="settings_signal_minimum_label">Kualitas sinyal minimum</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Dapatkan fitur tambahan &amp; bantu dukung pengembang.</string> <string name="upgrade_capod_description">Dapatkan fitur tambahan &amp; bantu dukung pengembang.</string>
<string name="settings_popup_caseopen_label">Tampilkan popup</string> <string name="settings_popup_caseopen_label">Tampilkan popup</string>
<string name="settings_popup_caseopen_description">Tampilkan popup saat kasing perangkat dibuka (eksperimental).</string> <string name="settings_popup_caseopen_description">Tampilkan popup saat kasing perangkat dibuka (eksperimental).</string>
<string name="notification_channel_reaction_popup_label">Reaksi perangkat popup</string>
<string name="overview_bluetooth_disabled_label">Bluetooth dinonaktifkan</string> <string name="overview_bluetooth_disabled_label">Bluetooth dinonaktifkan</string>
<string name="overview_bluetooth_disabled_description">Bluetooth dinonaktifkan, aktifkan terlebih dahulu ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth dinonaktifkan, aktifkan terlebih dahulu ;)</string>
<string name="help_translate_label">Terjemahan</string> <string name="help_translate_label">Terjemahan</string>
<string name="help_translate_description">Bantu terjemahkan ini ke bahasa favorit anda.</string> <string name="help_translate_description">Bantu terjemahkan applikasi ini ke bahasa favorit anda.</string>
<string name="settings_onepod_mode_label">Mode satu pod</string> <string name="settings_onepod_mode_label">Mode satu pod</string>
<string name="settings_onepod_mode_description">Menggunakan kedua pod tidak diperlukan, memakai satu pod sudah cukup untuk memicu reaksi.</string> <string name="settings_onepod_mode_description">Menggunakan kedua pod tidak diperlukan, memakai satu pod sudah cukup untuk memicu reaksi.</string>
<string name="permission_system_alert_window_label">Jendela Peringatan Sistem</string> <string name="permission_system_alert_window_label">Jendela Peringatan Sistem</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Data BLE yang tidak difilter</string> <string name="settings_blescanner_unfiltered_label">Data BLE yang tidak difilter</string>
<string name="settings_blescanner_unfiltered_description">Hapus semua filter dari pemindai BLE untuk menampilkan semua data BLE yang disiarkan. Berguna untuk menambahkan dukungan pada jenis headphone baru.</string> <string name="settings_blescanner_unfiltered_description">Hapus semua filter dari pemindai BLE untuk menampilkan semua data BLE yang disiarkan. Berguna untuk menambahkan dukungan pada jenis headphone baru.</string>
<string name="permission_required_title">Izin berikut diperlukan:</string> <string name="permission_required_title">Izin berikut diperlukan:</string>
<string name="settings_compatibility_mode_label">Mode kompatibilitas</string>
<string name="settings_compatibility_mode_description">Nonaktifkan pengoptimalan untuk meningkatkan kompatibilitas. Coba ini jika anda tidak melihat data apa pun.</string>
</resources> </resources>
+8 -4
View File
@@ -24,6 +24,7 @@
<string name="permission_bluetooth_scan_label">Scansione bluetooth</string> <string name="permission_bluetooth_scan_label">Scansione bluetooth</string>
<string name="permission_bluetooth_scan_description">Il permesso di \"Scansione bluetooth\" permette a questa app di trovare e ricevere dati Bluetooth da dispositivi vicini come le tue Airpods.</string> <string name="permission_bluetooth_scan_description">Il permesso di \"Scansione bluetooth\" permette a questa app di trovare e ricevere dati Bluetooth da dispositivi vicini come le tue Airpods.</string>
<string name="permission_bluetooth_label">Bluetooth</string> <string name="permission_bluetooth_label">Bluetooth</string>
<string name="permission_bluetooth_description">Questa app richiede il permesso \"Bluetooth\" per connettersi ai dispoitivi Bluetooth.</string>
<string name="permission_access_fine_location_label">Access fine location</string> <string name="permission_access_fine_location_label">Access fine location</string>
<string name="permission_access_fine_location_description">CAPod usa i permessi di Geolocalizzazione per ricevere dati Bluetooth a basso consumo. Le tue cuffie suano la tecnologia Bluetooth a basso consumo per inviare al dispositivo al quale sono connesse il loro stato. Questa app non utilizza i dati Bluetooth per geolocalizzarti.</string> <string name="permission_access_fine_location_description">CAPod usa i permessi di Geolocalizzazione per ricevere dati Bluetooth a basso consumo. Le tue cuffie suano la tecnologia Bluetooth a basso consumo per inviare al dispositivo al quale sono connesse il loro stato. Questa app non utilizza i dati Bluetooth per geolocalizzarti.</string>
<string name="permission_background_location_label">Accesso in background alla tua posizione</string> <string name="permission_background_location_label">Accesso in background alla tua posizione</string>
@@ -44,12 +45,14 @@
<string name="pods_connection_state_unknown_label">Stato di connessione sconosciuto</string> <string name="pods_connection_state_unknown_label">Stato di connessione sconosciuto</string>
<string name="pods_unknown_raw_data_label">Dati non elaborati</string> <string name="pods_unknown_raw_data_label">Dati non elaborati</string>
<string name="pods_unknown_label">Dispositivo sconosciuto</string> <string name="pods_unknown_label">Dispositivo sconosciuto</string>
<string name="pods_unknown_contact_dev">Questo é un dispositivo sconosciutom ma sta utilizzando un formato di comunicazione noto. Aggiungiamo il supporto per questo device, Contattami! :)</string>
<string name="pods_none_label_short">Nessun dispositivo</string> <string name="pods_none_label_short">Nessun dispositivo</string>
<string name="pods_charging_label">In ricarica</string> <string name="pods_charging_label">In ricarica</string>
<string name="pods_inear_label">Nell\'orecchio</string> <string name="pods_inear_label">Nell\'orecchio</string>
<string name="pods_microphone_label">Microfono</string> <string name="pods_microphone_label">Microfono</string>
<string name="pods_yours">Tuoi</string> <string name="pods_yours">Tuoi</string>
<string name="headset_being_worn_label">Indossato</string> <string name="headset_being_worn_label">Indossato</string>
<string name="pods_case_unknown_state">Stato sconosciuto</string>
<string name="overview_nomaindevice_label">Nessun device primario</string> <string name="overview_nomaindevice_label">Nessun device primario</string>
<string name="overview_nomaindevice_description">Tutti i dispositivi rilevati molto probabilmente non sono tuoi. Accendi e connetti i tuoi dispositivi oppure sistema le impostazioni.</string> <string name="overview_nomaindevice_description">Tutti i dispositivi rilevati molto probabilmente non sono tuoi. Accendi e connetti i tuoi dispositivi oppure sistema le impostazioni.</string>
<string name="settings_label">Impostazioni</string> <string name="settings_label">Impostazioni</string>
@@ -86,13 +89,11 @@
<string name="settings_scanner_mode_balanced_label">Bilanciato</string> <string name="settings_scanner_mode_balanced_label">Bilanciato</string>
<string name="settings_scanner_mode_lowlatency_label">Bassa latenza</string> <string name="settings_scanner_mode_lowlatency_label">Bassa latenza</string>
<string name="settings_autopause_label">Pausa automatica</string> <string name="settings_autopause_label">Pausa automatica</string>
<string name="settings_autopause_description">Metti in pausa la musica quando viene rimossa la cuffia da un orecchio.</string> <string name="settings_autopause_description">Metti in pausa l\'audio quando viene rimossa la cuffia da un orecchio.</string>
<string name="settings_showall_label">Mostra tutti i dispositivi</string> <string name="settings_showall_label">Mostra tutti i dispositivi</string>
<string name="settings_showall_description">Mostra i dispositivi delle altre persone vicine a te.</string> <string name="settings_showall_description">Mostra i dispositivi delle altre persone vicine a te.</string>
<string name="settings_autopplay_label">Riproduzione automatica</string> <string name="settings_autopplay_label">Riproduzione automatica</string>
<string name="settings_autoplay_description">Avvia la riproduzione della musica quando indossi il dispositivo.</string>
<string name="settings_fake_data_label">Dati immaginari</string> <string name="settings_fake_data_label">Dati immaginari</string>
<string name="settings_fake_data_description">Mostra dati immaginari così da poter simulare dispositivi che in realtà non esistono.</string>
<string name="settings_debug_label">Impostazioni di debug</string> <string name="settings_debug_label">Impostazioni di debug</string>
<string name="settings_debug_description">Impostazioni aggiuntive che possono aiutare a risolvere i problemi con l\'applicazione.</string> <string name="settings_debug_description">Impostazioni aggiuntive che possono aiutare a risolvere i problemi con l\'applicazione.</string>
<string name="settings_signal_minimum_label">Qualità del segnale minima</string> <string name="settings_signal_minimum_label">Qualità del segnale minima</string>
@@ -116,8 +117,8 @@
<string name="upgrade_capod_description">Ottieni funzionalità aggiuntive e supporta lo sviluppatore.</string> <string name="upgrade_capod_description">Ottieni funzionalità aggiuntive e supporta lo sviluppatore.</string>
<string name="settings_popup_caseopen_label">Mostra popup</string> <string name="settings_popup_caseopen_label">Mostra popup</string>
<string name="settings_popup_caseopen_description">Mostra un popup quando la custodia del dispositivo è aperta (sperimentale).</string> <string name="settings_popup_caseopen_description">Mostra un popup quando la custodia del dispositivo è aperta (sperimentale).</string>
<string name="notification_channel_reaction_popup_label">Popup reazioni dispositivo</string>
<string name="overview_bluetooth_disabled_label">Il Bluetooth é disabilitato</string> <string name="overview_bluetooth_disabled_label">Il Bluetooth é disabilitato</string>
<string name="overview_bluetooth_disabled_description">Il bluetooth é disabilitato, abilitalo ;)</string>
<string name="help_translate_label">Traduzione</string> <string name="help_translate_label">Traduzione</string>
<string name="help_translate_description">Aiuta a tradurre l\'applicazione nella tua lingua preferita.</string> <string name="help_translate_description">Aiuta a tradurre l\'applicazione nella tua lingua preferita.</string>
<string name="settings_onepod_mode_label">Modalità singolo pod</string> <string name="settings_onepod_mode_label">Modalità singolo pod</string>
@@ -126,4 +127,7 @@
<string name="permission_system_alert_window_description">Permetti a CAPod di far apprarire overlay sopra le altre applicazioni per far funzionare \"Mostra PopUp\".</string> <string name="permission_system_alert_window_description">Permetti a CAPod di far apprarire overlay sopra le altre applicazioni per far funzionare \"Mostra PopUp\".</string>
<string name="last_seen_x">Ultimo accesso: %s</string> <string name="last_seen_x">Ultimo accesso: %s</string>
<string name="first_seen_x">Primo accesso: %s</string> <string name="first_seen_x">Primo accesso: %s</string>
<string name="settings_blescanner_unfiltered_label">Dati BLE non filtrati</string>
<string name="permission_required_title">È richiesta la seguente autorizzazione:</string>
<string name="settings_compatibility_mode_label">Modalità di compatibilità</string>
</resources> </resources>
+6 -5
View File
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">מאוזן</string> <string name="settings_scanner_mode_balanced_label">מאוזן</string>
<string name="settings_scanner_mode_lowlatency_label">זמן אחזור נמוך</string> <string name="settings_scanner_mode_lowlatency_label">זמן אחזור נמוך</string>
<string name="settings_autopause_label">השהייה אוטומטית</string> <string name="settings_autopause_label">השהייה אוטומטית</string>
<string name="settings_autopause_description">השהה מוזיקה בעת הסרת המכשיר מהאוזן.</string> <string name="settings_autopause_description">עצירת אודיו בהסרת המכשיר מהאוזן.</string>
<string name="settings_showall_label">הצג את כל המכשירים</string> <string name="settings_showall_label">הצג את כל המכשירים</string>
<string name="settings_showall_description">הצג מכשירים של אנשים אחרים שנמצאים בקרבתך.</string> <string name="settings_showall_description">הצג מכשירים של אנשים אחרים שנמצאים בקרבתך.</string>
<string name="settings_autopplay_label">הפעלה אוטומטית</string> <string name="settings_autopplay_label">הפעלה אוטומטית</string>
<string name="settings_autoplay_description">התחל מוזיקה בהשמעת מוזיקה כאשר אתה לובש את המכשיר.</string> <string name="settings_autoplay_description">התחלת ניגון אודיו בלבישת המכשיר.</string>
<string name="settings_fake_data_label">נתונים מזויפים</string> <string name="settings_fake_data_label">נתונים מזויפים</string>
<string name="settings_fake_data_description">הצג נתונים מזויפים, כלומר הדמיית מכשיר שלא קיים.</string> <string name="settings_fake_data_description">הצגת נתונים מזויפים, לרבות, הדמיית מכשירים שאינם קיימים.</string>
<string name="settings_debug_label">הגדרות ניפוי באגים</string> <string name="settings_debug_label">הגדרות ניפוי באגים</string>
<string name="settings_debug_description">הגדרות נוספות שיסייעו בפתרון בעיות באפליקציה.</string> <string name="settings_debug_description">הגדרות נוספות שיסייעו בפתרון בעיות באפליקציה.</string>
<string name="settings_signal_minimum_label">איכות אות מינימלית</string> <string name="settings_signal_minimum_label">איכות אות מינימלית</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">קבל תכונות נוספות ותמיכה במפתח.</string> <string name="upgrade_capod_description">קבל תכונות נוספות ותמיכה במפתח.</string>
<string name="settings_popup_caseopen_label">הצג הודעה</string> <string name="settings_popup_caseopen_label">הצג הודעה</string>
<string name="settings_popup_caseopen_description">הצג חלון הודעה כאשר מארז המכשיר נפתח (ניסיוני).</string> <string name="settings_popup_caseopen_description">הצג חלון הודעה כאשר מארז המכשיר נפתח (ניסיוני).</string>
<string name="notification_channel_reaction_popup_label">תגובות חלון הודעוה של המכשיר</string>
<string name="overview_bluetooth_disabled_label">Bluetooth כבוי</string> <string name="overview_bluetooth_disabled_label">Bluetooth כבוי</string>
<string name="overview_bluetooth_disabled_description">בלוטות\' מכובה, יש להדליקו ;)</string> <string name="overview_bluetooth_disabled_description">בלוטות\' מכובה, יש להדליקו ;)</string>
<string name="help_translate_label">תרגום</string> <string name="help_translate_label">תרגום</string>
<string name="help_translate_description">עזור לתרגם את זה לשפה האהובה עליך.</string> <string name="help_translate_description">עזרו בתרגום אפליקציה זו לשפה המועדפת עליכם.</string>
<string name="settings_onepod_mode_label">מצב אוזניה בודדת</string> <string name="settings_onepod_mode_label">מצב אוזניה בודדת</string>
<string name="settings_onepod_mode_description">אין צורך לענוד את שני האוזניות, לבישת אוזניה בודדת מספיקה כדי לעורר תגובות.</string> <string name="settings_onepod_mode_description">אין צורך לענוד את שני האוזניות, לבישת אוזניה בודדת מספיקה כדי לעורר תגובות.</string>
<string name="permission_system_alert_window_label">חלון התראות מערכת</string> <string name="permission_system_alert_window_label">חלון התראות מערכת</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">נתוני BLE לא מפולטרים</string> <string name="settings_blescanner_unfiltered_label">נתוני BLE לא מפולטרים</string>
<string name="settings_blescanner_unfiltered_description">הסר מסננים מסורק BLE כדי להציג את כל נתוני BLE ששודרו. שימושי להוספת תמיכה בסוגי אוזניות חדשים.</string> <string name="settings_blescanner_unfiltered_description">הסר מסננים מסורק BLE כדי להציג את כל נתוני BLE ששודרו. שימושי להוספת תמיכה בסוגי אוזניות חדשים.</string>
<string name="permission_required_title">ההרשאה הבאה נדרשת:</string> <string name="permission_required_title">ההרשאה הבאה נדרשת:</string>
<string name="settings_compatibility_mode_label">מצב תאימות</string>
<string name="settings_compatibility_mode_description">נטרול אופטימיזציה לשיפור התאימות. נסו את זה אם לא מוצגים נתונים כלל.</string>
</resources> </resources>
+6 -5
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">모니터링 모드</string> <string name="settings_monitor_mode_label">모니터링 모드</string>
<string name="settings_monitor_mode_description">어떤 상황에서 블루투스 정보를 열람하는지 설정합니다.</string> <string name="settings_monitor_mode_description">어떤 상황에서 블루투스 정보를 열람하는지 설정합니다.</string>
<string name="settings_scanner_mode_label">스캐너 모드</string> <string name="settings_scanner_mode_label">스캐너 모드</string>
<string name="settings_scanner_mode_description">저전력 블루투스 스캐너가 성능과 전력 효율 중 무엇을 우선으로 할 지 선택합니다.</string> <string name="settings_scanner_mode_description">저전력 블루투스 데이터 스캐너가 성능과 전력 효율 중 무엇을 우선으로 할 지 선택합니다.</string>
<string name="settings_monitor_mode_manual_label">앱이 열려 있을 때</string> <string name="settings_monitor_mode_manual_label">앱이 열려 있을 때</string>
<string name="settings_monitor_mode_automatic_label">기기가 연결되어 있을 때</string> <string name="settings_monitor_mode_automatic_label">기기가 연결되어 있을 때</string>
<string name="settings_monitor_mode_always_label">항상</string> <string name="settings_monitor_mode_always_label">항상</string>
@@ -89,11 +89,11 @@
<string name="settings_scanner_mode_balanced_label">균형있게</string> <string name="settings_scanner_mode_balanced_label">균형있게</string>
<string name="settings_scanner_mode_lowlatency_label">저레이턴시</string> <string name="settings_scanner_mode_lowlatency_label">저레이턴시</string>
<string name="settings_autopause_label">자동 일시정지</string> <string name="settings_autopause_label">자동 일시정지</string>
<string name="settings_autopause_description">기기를 귀에서 뺄 때 음악을 일시정지합니다.</string> <string name="settings_autopause_description">기기를 귀에서 뺄 때 오디오를 일시정지합니다.</string>
<string name="settings_showall_label">모든 기기 보이기</string> <string name="settings_showall_label">모든 기기 보이기</string>
<string name="settings_showall_description">다른 사람의 기기도 보이게 합니다.</string> <string name="settings_showall_description">다른 사람의 기기도 보이게 합니다.</string>
<string name="settings_autopplay_label">자동 재생</string> <string name="settings_autopplay_label">자동 재생</string>
<string name="settings_autoplay_description">귀에 기기를 착용하면 음악을 시작합니다.</string> <string name="settings_autoplay_description">귀에 기기를 착용하면 오디오를 다시 시작합니다.</string>
<string name="settings_fake_data_label">가짜 데이터</string> <string name="settings_fake_data_label">가짜 데이터</string>
<string name="settings_fake_data_description">가짜 기기에 연결하는 것처럼 보이는 등 가짜 정보를 보여줍니다.</string> <string name="settings_fake_data_description">가짜 기기에 연결하는 것처럼 보이는 등 가짜 정보를 보여줍니다.</string>
<string name="settings_debug_label">디버그 설정</string> <string name="settings_debug_label">디버그 설정</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">개발자에게 후원하고 추가적 기능도 받습니다.</string> <string name="upgrade_capod_description">개발자에게 후원하고 추가적 기능도 받습니다.</string>
<string name="settings_popup_caseopen_label">팝업 보이기</string> <string name="settings_popup_caseopen_label">팝업 보이기</string>
<string name="settings_popup_caseopen_description">기기 케이스가 열렸을 때 팝업을 보여줍니다. (실험적)</string> <string name="settings_popup_caseopen_description">기기 케이스가 열렸을 때 팝업을 보여줍니다. (실험적)</string>
<string name="notification_channel_reaction_popup_label">팝업을 보일 기기 반응</string>
<string name="overview_bluetooth_disabled_label">블루투스 꺼져 있음</string> <string name="overview_bluetooth_disabled_label">블루투스 꺼져 있음</string>
<string name="overview_bluetooth_disabled_description">블루투스를 켜야 연결할 수 있어요 ;)</string> <string name="overview_bluetooth_disabled_description">블루투스를 켜야 연결할 수 있어요 ;)</string>
<string name="help_translate_label">번역</string> <string name="help_translate_label">번역</string>
<string name="help_translate_description">앱을 여러분의 언어로 번역하는 것을 도와주세요.</string> <string name="help_translate_description">앱을 여러분의 언어로 번역하는 것을 도와주세요.</string>
<string name="settings_onepod_mode_label">한쪽 기기 모드</string> <string name="settings_onepod_mode_label">한쪽 기기 모드</string>
<string name="settings_onepod_mode_description">양쪽 기기를 모두 착용할 필요 없이, 앱에서 한 쪽만 있어도 반응하도록 합니다.</string> <string name="settings_onepod_mode_description">양쪽 기기를 모두 착용할 필요 없이, 앱에서 한 쪽만 있어도 반응하도록 합니다.</string>
<string name="permission_system_alert_window_label">시스템 알림 창</string> <string name="permission_system_alert_window_label">시스템 알림 창</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">무보정 BLE 데이터</string> <string name="settings_blescanner_unfiltered_label">무보정 BLE 데이터</string>
<string name="settings_blescanner_unfiltered_description">BLE 스캐너에서 보정을 제거해 모든 BLE 정보를 보입니다. 새로운 모델에 대한 지원을 추가하기 좋습니다.</string> <string name="settings_blescanner_unfiltered_description">BLE 스캐너에서 보정을 제거해 모든 BLE 정보를 보입니다. 새로운 모델에 대한 지원을 추가하기 좋습니다.</string>
<string name="permission_required_title">다음 권한을 부여해야 합니다:</string> <string name="permission_required_title">다음 권한을 부여해야 합니다:</string>
<string name="settings_compatibility_mode_label">호환성 모드</string>
<string name="settings_compatibility_mode_description">최적화 설정들 몇 개를 비활성화해 호환성을 높입니다. 데이터가 보이지 않을 때 사용하세요.</string>
</resources> </resources>
+7 -6
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Mod monitor</string> <string name="settings_monitor_mode_label">Mod monitor</string>
<string name="settings_monitor_mode_description">Dalam keadaan yang mana apl ini memantau data Bluetooth.</string> <string name="settings_monitor_mode_description">Dalam keadaan yang mana apl ini memantau data Bluetooth.</string>
<string name="settings_scanner_mode_label">Mod pengimbas</string> <string name="settings_scanner_mode_label">Mod pengimbas</string>
<string name="settings_scanner_mode_description">Patutkah pengimbas Tenaga Rendah Bluetooth mengutamakan prestasi atau penjimatan tenaga?</string> <string name="settings_scanner_mode_description">Apakah sepatutnya pengimbas data Tenaga Rendah Bluetooth mengutamakan prestasi atau penjimatan tenaga?</string>
<string name="settings_monitor_mode_manual_label">Apabila apl dibuka</string> <string name="settings_monitor_mode_manual_label">Apabila apl dibuka</string>
<string name="settings_monitor_mode_automatic_label">Apabila peranti disambungkan</string> <string name="settings_monitor_mode_automatic_label">Apabila peranti disambungkan</string>
<string name="settings_monitor_mode_always_label">Sentiasa</string> <string name="settings_monitor_mode_always_label">Sentiasa</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Seimbang</string> <string name="settings_scanner_mode_balanced_label">Seimbang</string>
<string name="settings_scanner_mode_lowlatency_label">Latensi rendah</string> <string name="settings_scanner_mode_lowlatency_label">Latensi rendah</string>
<string name="settings_autopause_label">Auto jeda</string> <string name="settings_autopause_label">Auto jeda</string>
<string name="settings_autopause_description">Jeda muzik apabila peranti dikeluarkan dari telinga anda.</string> <string name="settings_autopause_description">Jeda audio apabila peranti dikeluarkan dari telinga anda.</string>
<string name="settings_showall_label">Tunjukkan semua peranti</string> <string name="settings_showall_label">Tunjukkan semua peranti</string>
<string name="settings_showall_description">Tunjukkan peranti orang lain yang berdekatan dengan anda.</string> <string name="settings_showall_description">Tunjukkan peranti orang lain yang berdekatan dengan anda.</string>
<string name="settings_autopplay_label">Auto main</string> <string name="settings_autopplay_label">Auto main</string>
<string name="settings_autoplay_description">Mulakan muzik main balik muzik apabila memakai peranti.</string> <string name="settings_autoplay_description">Mulakan main balik audio apabila peranti dipakai.</string>
<string name="settings_fake_data_label">Data palsu</string> <string name="settings_fake_data_label">Data palsu</string>
<string name="settings_fake_data_description">Tunjukkan data palsu, i.e. simulasi peranti yang tidak wujud.</string> <string name="settings_fake_data_description">Tunjukkan data palsu, yakni, simulasi peranti yang tidak wujud.</string>
<string name="settings_debug_label">Tetapan nyahpepijat</string> <string name="settings_debug_label">Tetapan nyahpepijat</string>
<string name="settings_debug_description">Tetapan tambahan untuk membantu menyelesaikan isu dengan apl.</string> <string name="settings_debug_description">Tetapan tambahan untuk membantu menyelesaikan isu dengan apl.</string>
<string name="settings_signal_minimum_label">Kualiti isyarat minimum</string> <string name="settings_signal_minimum_label">Kualiti isyarat minimum</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Dapatkan ciri tambahan dan sokongi pemaju.</string> <string name="upgrade_capod_description">Dapatkan ciri tambahan dan sokongi pemaju.</string>
<string name="settings_popup_caseopen_label">Tunjukkan popup</string> <string name="settings_popup_caseopen_label">Tunjukkan popup</string>
<string name="settings_popup_caseopen_description">Tunjukkan popup apabila sarung peranti dibuka (percubaan).</string> <string name="settings_popup_caseopen_description">Tunjukkan popup apabila sarung peranti dibuka (percubaan).</string>
<string name="notification_channel_reaction_popup_label">Reaksi peranti popup</string>
<string name="overview_bluetooth_disabled_label">Bluetooth dinyahdayakan</string> <string name="overview_bluetooth_disabled_label">Bluetooth dinyahdayakan</string>
<string name="overview_bluetooth_disabled_description">Bluetooth dinyahdayakan, dayakan ia ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth dinyahdayakan, dayakan ia ;)</string>
<string name="help_translate_label">Terjemahan</string> <string name="help_translate_label">Terjemahan</string>
<string name="help_translate_description">Bantu menterjemahkan ini ke dalam bahasa kegemaran anda.</string> <string name="help_translate_description">Bantu terjemahkan apl ini ke dalam bahasa kegemaran anda.</string>
<string name="settings_onepod_mode_label">Satu mod pod</string> <string name="settings_onepod_mode_label">Satu mod pod</string>
<string name="settings_onepod_mode_description">Tidak perlu memakai kedua-dua pod, memakai satu pod sudah memadai untuk mencetuskan tindak balas.</string> <string name="settings_onepod_mode_description">Tidak perlu memakai kedua-dua pod, memakai satu pod sudah memadai untuk mencetuskan tindak balas.</string>
<string name="permission_system_alert_window_label">Tetingkap Makluman Sistem</string> <string name="permission_system_alert_window_label">Tetingkap Makluman Sistem</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Data BLE tanpa tapisan</string> <string name="settings_blescanner_unfiltered_label">Data BLE tanpa tapisan</string>
<string name="settings_blescanner_unfiltered_description">Alih keluar sebarang tapisan daripada pengimbas BLE untuk menunjukkan semua data BLE yang disiarkan. Berguna bagi menambah sokongan untuk jenis fon kepala baharu.</string> <string name="settings_blescanner_unfiltered_description">Alih keluar sebarang tapisan daripada pengimbas BLE untuk menunjukkan semua data BLE yang disiarkan. Berguna bagi menambah sokongan untuk jenis fon kepala baharu.</string>
<string name="permission_required_title">Kebenaran berikut diperlukan:</string> <string name="permission_required_title">Kebenaran berikut diperlukan:</string>
<string name="settings_compatibility_mode_label">Mod keserasian</string>
<string name="settings_compatibility_mode_description">Nyahdayakan pengoptimuman untuk tingkatkan keserasian. Cuba ini jika anda tidak melihat sebarang data.</string>
</resources> </resources>
+5 -4
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Monitor modus</string> <string name="settings_monitor_mode_label">Monitor modus</string>
<string name="settings_monitor_mode_description">Onder welke omstandigheden houdt deze app Bluetooth-gegevens bij.</string> <string name="settings_monitor_mode_description">Onder welke omstandigheden houdt deze app Bluetooth-gegevens bij.</string>
<string name="settings_scanner_mode_label">Scannermodus</string> <string name="settings_scanner_mode_label">Scannermodus</string>
<string name="settings_scanner_mode_description">Moet de Bluetooth Low Energy-scanner voorrang geven aan prestaties of energie besparen?</string> <string name="settings_scanner_mode_description">Moet de Bluetooth Low Energy-gegevensscanner prioriteit geven aan prestaties of energie besparen?</string>
<string name="settings_monitor_mode_manual_label">Wanneer app is geopend</string> <string name="settings_monitor_mode_manual_label">Wanneer app is geopend</string>
<string name="settings_monitor_mode_automatic_label">Wanneer het apparaat is aangesloten</string> <string name="settings_monitor_mode_automatic_label">Wanneer het apparaat is aangesloten</string>
<string name="settings_monitor_mode_always_label">Altijd</string> <string name="settings_monitor_mode_always_label">Altijd</string>
@@ -93,7 +93,7 @@
<string name="settings_showall_label">Alle apparaten weergeven</string> <string name="settings_showall_label">Alle apparaten weergeven</string>
<string name="settings_showall_description">Toon apparaten van andere mensen die bij u in de buurt zijn.</string> <string name="settings_showall_description">Toon apparaten van andere mensen die bij u in de buurt zijn.</string>
<string name="settings_autopplay_label">Automatisch afspelen</string> <string name="settings_autopplay_label">Automatisch afspelen</string>
<string name="settings_autoplay_description">Start het afspelen van muziek wanneer u het apparaat draagt.</string> <string name="settings_autoplay_description">Start audioweergave wanneer het apparaat wordt gedragen.</string>
<string name="settings_fake_data_label">Nep gegevens</string> <string name="settings_fake_data_label">Nep gegevens</string>
<string name="settings_fake_data_description">Toon nepgegevens, d.w.z. simuleer apparaten die niet bestaan.</string> <string name="settings_fake_data_description">Toon nepgegevens, d.w.z. simuleer apparaten die niet bestaan.</string>
<string name="settings_debug_label">Foutopsporingsinstellingen</string> <string name="settings_debug_label">Foutopsporingsinstellingen</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Krijg extra functies en ondersteun de ontwikkelaar.</string> <string name="upgrade_capod_description">Krijg extra functies en ondersteun de ontwikkelaar.</string>
<string name="settings_popup_caseopen_label">Pop-up weergeven</string> <string name="settings_popup_caseopen_label">Pop-up weergeven</string>
<string name="settings_popup_caseopen_description">Een pop-up weergeven wanneer de behuizing van het apparaat wordt geopend (experimenteel).</string> <string name="settings_popup_caseopen_description">Een pop-up weergeven wanneer de behuizing van het apparaat wordt geopend (experimenteel).</string>
<string name="notification_channel_reaction_popup_label">Pop-up apparaatreacties</string>
<string name="overview_bluetooth_disabled_label">Bluetooth is uitgeschakeld</string> <string name="overview_bluetooth_disabled_label">Bluetooth is uitgeschakeld</string>
<string name="overview_bluetooth_disabled_description">Bluetooth is uitgeschakeld, activeer het ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth is uitgeschakeld, activeer het ;)</string>
<string name="help_translate_label">Vertaling</string> <string name="help_translate_label">Vertaling</string>
<string name="help_translate_description">Help dit te vertalen naar uw favoriete taal.</string> <string name="help_translate_description">Help deze app te vertalen in uw favoriete taal.</string>
<string name="settings_onepod_mode_label">Eén pod-modus</string> <string name="settings_onepod_mode_label">Eén pod-modus</string>
<string name="settings_onepod_mode_description">Het dragen van beide pods is niet vereist, het dragen van een enkele pod is voldoende om reacties uit te lokken.</string> <string name="settings_onepod_mode_description">Het dragen van beide pods is niet vereist, het dragen van een enkele pod is voldoende om reacties uit te lokken.</string>
<string name="permission_system_alert_window_label">Systeemwaarschuwingsvenster</string> <string name="permission_system_alert_window_label">Systeemwaarschuwingsvenster</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Ongefilterde BLE-gegevens</string> <string name="settings_blescanner_unfiltered_label">Ongefilterde BLE-gegevens</string>
<string name="settings_blescanner_unfiltered_description">Verwijder eventuele filters van de BLE-scanner om alle uitgezonden BLE-gegevens weer te geven. Handig om ondersteuning toe te voegen voor nieuwe typen hoofdtelefoons.</string> <string name="settings_blescanner_unfiltered_description">Verwijder eventuele filters van de BLE-scanner om alle uitgezonden BLE-gegevens weer te geven. Handig om ondersteuning toe te voegen voor nieuwe typen hoofdtelefoons.</string>
<string name="permission_required_title">De volgende toestemming is vereist:</string> <string name="permission_required_title">De volgende toestemming is vereist:</string>
<string name="settings_compatibility_mode_label">Compatibiliteitsmodus</string>
<string name="settings_compatibility_mode_description">Schakel optimalisaties uit om de compatibiliteit te verbeteren. Probeer dit als u geen gegevens ziet.</string>
</resources> </resources>
+136 -1
View File
@@ -1,2 +1,137 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources></resources> <resources>
<string name="app_name">CAPod</string>
<string name="app_name_pro">CAPod Pro</string>
<string name="app_name_foss">CAPod FOSS</string>
<string name="notification_channel_device_status_label">Enhetsstatus</string>
<string name="general_error_label">Feil</string>
<string name="general_share_action">Del</string>
<string name="general_done_action">Ferdig</string>
<string name="general_copy_action">Kopier</string>
<string name="general_thank_you_label">Tusen takk</string>
<string name="general_value_not_available_label">N/A</string>
<string name="general_grant_permission_action">Gi tillatelse</string>
<string name="general_upgrade_action">Oppgrader</string>
<string name="general_check_action">Sjekk</string>
<string name="general_close_action">Lukk</string>
<string name="debug_debuglog_size_label">Størrelse</string>
<string name="debug_debuglog_size_compressed_label">Komprimert størrelse</string>
<string name="debug_notification_channel_label">Feilsøkingsvarslinger</string>
<string name="debug_debuglog_file_label">Registrert loggfil</string>
<string name="debug_debuglog_record_action">Registrer feilsøkingslogg</string>
<string name="permission_bluetooth_connect_label">Bluetooth-tilkobling</string>
<string name="permission_bluetooth_connect_description">Denne appen må ha \"Bluetooth-tilkobling\"-tillatelsen for å kunne snakke med sammenkoblede enheter og starte tilkoblinger.</string>
<string name="permission_bluetooth_scan_label">Bluetooth-skanning</string>
<string name="permission_bluetooth_scan_description">\"Bluetooth-skanning\"-tillatelsen lar denne appen oppdage og motta Bluetooth-data fra enheter i nærheten, som for eksempel AirPods.</string>
<string name="permission_bluetooth_label">Bluetooth</string>
<string name="permission_bluetooth_description">Denne appen må ha \"Bluetooth\"-tillatelsen for å koble til sammenkoblede Bluetooth-enheter.</string>
<string name="permission_access_fine_location_label">Forbedret posisjonsnøyaktighet</string>
<string name="permission_access_fine_location_description">CAPod bruker tillatelsen \"Forbedret posisjonsnøyaktighet\" for å motta Bluetooth Low Energy-data. Hodetelefonene dine bruker Bluetooth Low Energy-teknologi for å kringkaste statusen. Denne appen bruker IKKE Bluetooth-data til å se posisjonen din.</string>
<string name="permission_background_location_label">Bakgrunnsposisjon</string>
<string name="permission_background_location_description">CAPod bruker \"Bakgrunnsposisjon\" for å aktivere funksjoner som \"Vis popup\" og \"Autotilkobling\" mens appen er lukket. Tilgang til bakgrunnsposisjon lar appen motta Bluetooth Low Energy-data mens den er i bakgrunnen. Denne appen bruker IKKE Bluetooth-data for å se posisjonen din.</string>
<string name="permission_ignore_battery_optimizations_label">Deaktiver batterioptimalisering</string>
<string name="permission_ignore_battery_optimizations_description">Batterioptimalisering gjør at denne appen ikke alltid kan motta Bluetooth-data mens den er i bakgrunnen.</string>
<string name="pods_dual_left_label">Venstre pod</string>
<string name="pods_dual_right_label">Høyre pod</string>
<string name="pods_case_label">Deksel</string>
<string name="pods_case_status_open_label">Åpen</string>
<string name="pods_case_status_closed_label">Lukket</string>
<string name="pods_connection_state_disconnected_label">Ikke koblet til en enhet</string>
<string name="pods_connection_state_idle_label">Koblet til en enhet, men inaktiv</string>
<string name="pods_connection_state_music_label">I musikkmodus</string>
<string name="pods_connection_state_call_label">I ringemodus</string>
<string name="pods_connection_state_ringing_label">Ringer</string>
<string name="pods_connection_state_hanging_up_label">Legger på</string>
<string name="pods_connection_state_unknown_label">Ukjent tilkoblingsstatus</string>
<string name="pods_unknown_raw_data_label">Rådata</string>
<string name="pods_unknown_label">Ukjent enhet</string>
<string name="pods_unknown_contact_dev">Dette er en ukjent enhet, men den har en lignende meldingsformat. Vi kan legge til støtte for den, kontakt meg :)</string>
<string name="pods_none_label_short">Ingen enhet</string>
<string name="pods_charging_label">Lader</string>
<string name="pods_inear_label">I øret</string>
<string name="pods_microphone_label">Mikrofon</string>
<string name="pods_yours">Dine</string>
<string name="headset_being_worn_label">Brukes</string>
<string name="pods_case_unknown_state">Ukjent status</string>
<string name="overview_nomaindevice_label">Ingen primær enhet</string>
<string name="overview_nomaindevice_description">Det er usannsynlig at alle oppdagede enheter er dine. Slå på og koble til enheten eller juster innstillingene.</string>
<string name="settings_label">Innstillinger</string>
<string name="settings_privacy_policy_label">Personvernerklæring</string>
<string name="settings_privacy_policy_desc">Håndterer data ansvarlig.</string>
<string name="settings_licenses_label">Lisenser</string>
<string name="settings_category_other_label">Annet</string>
<string name="settings_general_label">Innstillinger</string>
<string name="settings_general_description">Generelle justeringer som påvirker hele appen.</string>
<string name="settings_acknowledgements_label">Anerkjennelser</string>
<string name="changelog_label">Endringslogg</string>
<string name="settings_support_email_developer_label">Send e-post til utvikler</string>
<string name="settings_support_installid_label">Installasjons-ID</string>
<string name="settings_support_installid_desc">Automatiske feilrapporter er anonyme. Del installasjons-ID-en din hvis utvikleren skal finne feilrapportene dine.</string>
<string name="settings_support_label">Brukerstøtte</string>
<string name="settings_support_description">Hvis du trenger hjelp med noe.</string>
<string name="issue_tracker_label">Problemsporing</string>
<string name="issue_tracker_description">En offentlig problemsporing for feilrapporter og funksjonsforespørsler (kun på engelsk).</string>
<string name="discord_label">Discord</string>
<string name="discord_description">Et sted til å henge og for å stille spørsmål.</string>
<string name="settings_support_email_developer_description">Merk at jeg bare kan svare på tysk eller engelsk.</string>
<string name="settings_debug_autoreports_label">Automatiske feilrapporter</string>
<string name="settings_debug_autoreports_description">Rapporterer problemer automatisk, f.eks. detaljer om en appkrasj slik at jeg kan finne ut hvordan jeg kan fikse det.</string>
<string name="settings_debug_mode_label">Feilsøkingsmodus</string>
<string name="settings_debug_mode_description">Vis tilleggsinformasjon for å feilsøke problemer.</string>
<string name="settings_monitor_mode_label">Overvåkingsmodus</string>
<string name="settings_monitor_mode_description">Under hvilke omstendigheter denne appen skal overvåke Bluetooth-data.</string>
<string name="settings_scanner_mode_label">Skannermodus</string>
<string name="settings_scanner_mode_description">Skal Bluetooth Low Energy data-skanneren prioritere ytelse eller å spare energi?</string>
<string name="settings_monitor_mode_manual_label">Når appen er åpen</string>
<string name="settings_monitor_mode_automatic_label">Når enheten er tilkoblet</string>
<string name="settings_monitor_mode_always_label">Alltid</string>
<string name="settings_scanner_mode_lowpower_label">Lavt strømforbruk</string>
<string name="settings_scanner_mode_balanced_label">Balansert</string>
<string name="settings_scanner_mode_lowlatency_label">Lav forsinkelse</string>
<string name="settings_autopause_label">Sett på pause automatisk</string>
<string name="settings_autopause_description">Sett lyden på pause når du fjerner enheten fra øret.</string>
<string name="settings_showall_label">Vis alle enheter</string>
<string name="settings_showall_description">Vis andres enheter som er i nærheten av deg.</string>
<string name="settings_autopplay_label">Spill av automatisk</string>
<string name="settings_autoplay_description">Spill av lyd når enheten er i bruk.</string>
<string name="settings_fake_data_label">Falsk data</string>
<string name="settings_fake_data_description">Vis falsk data, dvs. simuler enheter som ikke eksisterer.</string>
<string name="settings_debug_label">Feilsøkingsinnstillinger</string>
<string name="settings_debug_description">Ytterligere innstillinger til å hjelpe med feilsøking av problemer i appen.</string>
<string name="settings_signal_minimum_label">Minimum signalkvalitet</string>
<string name="settings_signal_minimum_description">Minimumssignalkvaliteten som en enhet må ha for å anses som din.</string>
<string name="settings_autoconnect_label">Autotilkobling</string>
<string name="settings_autoconnect_description">Hvis Android ikke kobler til automatisk, kan vi spørre den om å gjøre det. Dette vil sette overvåkingsmodus-innstillingen til \'Alltid\'.</string>
<string name="settings_autoconnect_condition_label">Betingelse for autotilkobling</string>
<string name="settings_autoconnect_condition_description">Når skal vi prøve å koble til enheten din?</string>
<string name="settings_reaction_label">Reaksjoner</string>
<string name="settings_reaction_description">Reager på hendelser og oppførsel.</string>
<string name="settings_category_yourdevice_label">Enheten din</string>
<string name="settings_maindevice_address_label">Enhetens adresse</string>
<string name="settings_maindevice_address_description">Adressen til den sammenkoblede enheten. Appen bruker denne til å finne ut når den er koblet til telefonen din.</string>
<string name="settings_maindevice_address_none">Ingen</string>
<string name="settings_maindevice_model_label">Enhetens modell</string>
<string name="settings_maindevice_model_description">Modellen til hovedenheten din. Dette hjelper appen med å gjenkjenne enheten din når den ikke er koblet til telefonen.</string>
<string name="settings_reaction_autoconnect_whenseen_label">Når sett</string>
<string name="settings_reaction_autoconnect_caseopen_label">Deksel er åpen</string>
<string name="settings_reaction_autoconnect_inear_label">I øret</string>
<string name="upgrade_capod_label">Oppgrader CAPod</string>
<string name="upgrade_capod_description">Få flere funksjoner og støtt utvikleren.</string>
<string name="settings_popup_caseopen_label">Vis popup</string>
<string name="settings_popup_caseopen_description">Vis en popup når enhetens deksel åpnes (eksperimentelt).</string>
<string name="overview_bluetooth_disabled_label">Bluetooth er deaktivert</string>
<string name="overview_bluetooth_disabled_description">Bluetooth er deaktivert, aktiver det ;)</string>
<string name="help_translate_label">Oversettelse</string>
<string name="help_translate_description">Hjelp til med å oversette denne appen til ditt favorittspråk.</string>
<string name="settings_onepod_mode_label">En pod modus</string>
<string name="settings_onepod_mode_description">Du trenger kun ha på deg en pod for å utløse reaksjoner, i stedet for begge.</string>
<string name="permission_system_alert_window_label">Systemvarslingsvindu</string>
<string name="permission_system_alert_window_description">La CAPod tegne over andre apper for å gjøre \"Vis popup\"-funksjonen mulig.</string>
<string name="last_seen_x">Sist sett: %s</string>
<string name="first_seen_x">Først sett: %s</string>
<string name="settings_blescanner_unfiltered_label">Ufiltrert BLE-data</string>
<string name="settings_blescanner_unfiltered_description">Fjern eventuelle filtre fra BLE-skanneren for å vise alle kringkastede BLE-data. Nyttig for å kunne støtte nye hodetelefontyper.</string>
<string name="permission_required_title">Følgende tillatelse kreves:</string>
<string name="settings_compatibility_mode_label">Kompatibilitetsmodus</string>
<string name="settings_compatibility_mode_description">Deaktiver optimaliseringer for å forbedre kompatibiliteten. Prøv dette hvis du ikke ser noen data.</string>
</resources>
+6 -5
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Tryb monitorowania</string> <string name="settings_monitor_mode_label">Tryb monitorowania</string>
<string name="settings_monitor_mode_description">W pewnych okolicznościach aplikacja może monitorować dane Bluetooth.</string> <string name="settings_monitor_mode_description">W pewnych okolicznościach aplikacja może monitorować dane Bluetooth.</string>
<string name="settings_scanner_mode_label">Tryb skanera</string> <string name="settings_scanner_mode_label">Tryb skanera</string>
<string name="settings_scanner_mode_description">Czy skaner Bluetooth Low Energy ma priorytetowo działać w ramach wydajności czy oszczędzania energii?</string> <string name="settings_scanner_mode_description">Czy skaner danych Bluetooth Low Energy ma priorytetowo działać w ramach wydajności czy oszczędzania energii?</string>
<string name="settings_monitor_mode_manual_label">Gdy aplikacja jest uruchomiona</string> <string name="settings_monitor_mode_manual_label">Gdy aplikacja jest uruchomiona</string>
<string name="settings_monitor_mode_automatic_label">Gdy urządzenie jest podłączone</string> <string name="settings_monitor_mode_automatic_label">Gdy urządzenie jest podłączone</string>
<string name="settings_monitor_mode_always_label">Zawsze</string> <string name="settings_monitor_mode_always_label">Zawsze</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Zabalansowana</string> <string name="settings_scanner_mode_balanced_label">Zabalansowana</string>
<string name="settings_scanner_mode_lowlatency_label">Małe opóźnienia</string> <string name="settings_scanner_mode_lowlatency_label">Małe opóźnienia</string>
<string name="settings_autopause_label">Automatyczna pauza</string> <string name="settings_autopause_label">Automatyczna pauza</string>
<string name="settings_autopause_description">Pauzuj muzykę, gdy urządzenia jest wyciągane z ucha.</string> <string name="settings_autopause_description">Pauzuj odtwarzanie, gdy urządzenia jest wyciągane z ucha.</string>
<string name="settings_showall_label">Wyświetl wszystkie urządzenia</string> <string name="settings_showall_label">Wyświetl wszystkie urządzenia</string>
<string name="settings_showall_description">Wyświetla urządzenia innych osób, które są w pobliżu.</string> <string name="settings_showall_description">Wyświetla urządzenia innych osób, które są w pobliżu.</string>
<string name="settings_autopplay_label">Automatyczne odtwarzanie</string> <string name="settings_autopplay_label">Automatyczne odtwarzanie</string>
<string name="settings_autoplay_description">Uruchamia odtwarzanie muzyki, gdy urządzenie jest noszone.</string> <string name="settings_autoplay_description">Rozpocznij odtwarzanie, gdy urządzenie jest noszone.</string>
<string name="settings_fake_data_label">Fałszywe dane</string> <string name="settings_fake_data_label">Fałszywe dane</string>
<string name="settings_fake_data_description">Wyświetla fałszywe dane, na przykłady w celu symulowania urządzenia, które nie istnieje.</string> <string name="settings_fake_data_description">Wyświetla fałszywe dane, na przykłady symuluje urządzenie, które nie istnieje.</string>
<string name="settings_debug_label">Ustawienia debugowania</string> <string name="settings_debug_label">Ustawienia debugowania</string>
<string name="settings_debug_description">Dodatkowe ustawienia, które pomogą rozwiązać problemy z aplikacją.</string> <string name="settings_debug_description">Dodatkowe ustawienia, które pomogą rozwiązać problemy z aplikacją.</string>
<string name="settings_signal_minimum_label">Minimalna jakość sygnału</string> <string name="settings_signal_minimum_label">Minimalna jakość sygnału</string>
@@ -119,7 +119,6 @@
<string name="upgrade_capod_description">Uzyskaj dodatkowe funkcjonalności i wesprzyj autora.</string> <string name="upgrade_capod_description">Uzyskaj dodatkowe funkcjonalności i wesprzyj autora.</string>
<string name="settings_popup_caseopen_label">Wyświetlanie informacji</string> <string name="settings_popup_caseopen_label">Wyświetlanie informacji</string>
<string name="settings_popup_caseopen_description">Wyświetla informację, gdy obudowa urządzenia jest otwarta (eksperymentalnie).</string> <string name="settings_popup_caseopen_description">Wyświetla informację, gdy obudowa urządzenia jest otwarta (eksperymentalnie).</string>
<string name="notification_channel_reaction_popup_label">Informacje o reakcjach urządzenia</string>
<string name="overview_bluetooth_disabled_label">Bluetooth jest wyłączony</string> <string name="overview_bluetooth_disabled_label">Bluetooth jest wyłączony</string>
<string name="overview_bluetooth_disabled_description">Bluetooth jest wyłączony, włącz go ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth jest wyłączony, włącz go ;)</string>
<string name="help_translate_label">Tłumaczenie</string> <string name="help_translate_label">Tłumaczenie</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Niefiltrowane dane BLE</string> <string name="settings_blescanner_unfiltered_label">Niefiltrowane dane BLE</string>
<string name="settings_blescanner_unfiltered_description">Usuwa wszystkie filtry ze skaner BLE, aby wyświetlić wszystkie nadawane dane BLE. Użyteczne w przypadku dodawania obsługi nowego typu słuchawek.</string> <string name="settings_blescanner_unfiltered_description">Usuwa wszystkie filtry ze skaner BLE, aby wyświetlić wszystkie nadawane dane BLE. Użyteczne w przypadku dodawania obsługi nowego typu słuchawek.</string>
<string name="permission_required_title">Następujące uprawnienie jest wymagane:</string> <string name="permission_required_title">Następujące uprawnienie jest wymagane:</string>
<string name="settings_compatibility_mode_label">Tryb kompatybilność</string>
<string name="settings_compatibility_mode_description">Wyłącza optymalizacje, aby poprawić kompatybilność. Wypróbuj, jeśli nie widzisz żadnych danych.</string>
</resources> </resources>
+7 -6
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Modo de monitoramento</string> <string name="settings_monitor_mode_label">Modo de monitoramento</string>
<string name="settings_monitor_mode_description">Sob quais circunstâncias este aplicativo monitora os dados do Bluetooth.</string> <string name="settings_monitor_mode_description">Sob quais circunstâncias este aplicativo monitora os dados do Bluetooth.</string>
<string name="settings_scanner_mode_label">Modo de escaneamento</string> <string name="settings_scanner_mode_label">Modo de escaneamento</string>
<string name="settings_scanner_mode_description">O escaneamento Bluetooth Low Energy deve priorizar o desempenho ou economizar energia?</string> <string name="settings_scanner_mode_description">O scanner de dados Bluetooth Low Energy deve priorizar o desempenho ou economizar energia?</string>
<string name="settings_monitor_mode_manual_label">Quando o aplicativo está aberto</string> <string name="settings_monitor_mode_manual_label">Quando o aplicativo está aberto</string>
<string name="settings_monitor_mode_automatic_label">Quando o dispositivo está conectado</string> <string name="settings_monitor_mode_automatic_label">Quando o dispositivo está conectado</string>
<string name="settings_monitor_mode_always_label">Sempre</string> <string name="settings_monitor_mode_always_label">Sempre</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Balanceado</string> <string name="settings_scanner_mode_balanced_label">Balanceado</string>
<string name="settings_scanner_mode_lowlatency_label">Baixa latência</string> <string name="settings_scanner_mode_lowlatency_label">Baixa latência</string>
<string name="settings_autopause_label">Pausa automática</string> <string name="settings_autopause_label">Pausa automática</string>
<string name="settings_autopause_description">Pause a música ao remover o dispositivo do ouvido.</string> <string name="settings_autopause_description">Pause o áudio ao remover o dispositivo do ouvido.</string>
<string name="settings_showall_label">Mostrar todos os dispositivos</string> <string name="settings_showall_label">Mostrar todos os dispositivos</string>
<string name="settings_showall_description">Mostre os dispositivos de outras pessoas que estão perto de você.</string> <string name="settings_showall_description">Mostre os dispositivos de outras pessoas que estão perto de você.</string>
<string name="settings_autopplay_label">Reprodução automática</string> <string name="settings_autopplay_label">Reprodução automática</string>
<string name="settings_autoplay_description">Inicie a reprodução da música ao usar o dispositivo.</string> <string name="settings_autoplay_description">Inicie a reprodução de áudio quando o dispositivo estiver em uso.</string>
<string name="settings_fake_data_label">Dados falsos</string> <string name="settings_fake_data_label">Dados falsos</string>
<string name="settings_fake_data_description">Mostrar dados falsos, ou seja, simular dispositivos que não existem.</string> <string name="settings_fake_data_description">Mostre dados falsos, ou seja, simule dispositivos que não existem.</string>
<string name="settings_debug_label">Configurações de depuração</string> <string name="settings_debug_label">Configurações de depuração</string>
<string name="settings_debug_description">Configurações adicionais para ajudar a solucionar problemas com o aplicativo.</string> <string name="settings_debug_description">Configurações adicionais para ajudar a solucionar problemas com o aplicativo.</string>
<string name="settings_signal_minimum_label">Qualidade mínima do sinal</string> <string name="settings_signal_minimum_label">Qualidade mínima do sinal</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Obtenha recursos adicionais e dê suporte ao desenvolvedor.</string> <string name="upgrade_capod_description">Obtenha recursos adicionais e dê suporte ao desenvolvedor.</string>
<string name="settings_popup_caseopen_label">Mostrar pop-up</string> <string name="settings_popup_caseopen_label">Mostrar pop-up</string>
<string name="settings_popup_caseopen_description">Mostrar um pop-up quando o estojo do dispositivo for aberta (experimental).</string> <string name="settings_popup_caseopen_description">Mostrar um pop-up quando o estojo do dispositivo for aberta (experimental).</string>
<string name="notification_channel_reaction_popup_label">Reações pop-up do dispositivo</string>
<string name="overview_bluetooth_disabled_label">Bluetooth está desativado</string> <string name="overview_bluetooth_disabled_label">Bluetooth está desativado</string>
<string name="overview_bluetooth_disabled_description">O Bluetooth está desabilitado, habilite-o ;)</string> <string name="overview_bluetooth_disabled_description">O Bluetooth está desabilitado, habilite-o ;)</string>
<string name="help_translate_label">Tradução</string> <string name="help_translate_label">Tradução</string>
<string name="help_translate_description">Ajude a traduzir isso para o seu idioma favorito.</string> <string name="help_translate_description">Ajude a traduzir este aplicativo para seu idioma favorito.</string>
<string name="settings_onepod_mode_label">Modo de um airpod</string> <string name="settings_onepod_mode_label">Modo de um airpod</string>
<string name="settings_onepod_mode_description">Não é necessário usar os dois airpods, usar um único airpod é suficiente para destravar reações.</string> <string name="settings_onepod_mode_description">Não é necessário usar os dois airpods, usar um único airpod é suficiente para destravar reações.</string>
<string name="permission_system_alert_window_label">Janela de alerta do sistema</string> <string name="permission_system_alert_window_label">Janela de alerta do sistema</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Dados BLE não filtrados</string> <string name="settings_blescanner_unfiltered_label">Dados BLE não filtrados</string>
<string name="settings_blescanner_unfiltered_description">Remova quaisquer filtros do scanner BLE para mostrar todos os dados BLE transmitidos. Útil para adicionar suporte para novos tipos de fones de ouvido.</string> <string name="settings_blescanner_unfiltered_description">Remova quaisquer filtros do scanner BLE para mostrar todos os dados BLE transmitidos. Útil para adicionar suporte para novos tipos de fones de ouvido.</string>
<string name="permission_required_title">A seguinte permissão é necessária:</string> <string name="permission_required_title">A seguinte permissão é necessária:</string>
<string name="settings_compatibility_mode_label">Modo de compatibilidade</string>
<string name="settings_compatibility_mode_description">Desative as otimizações para melhorar a compatibilidade. Tente isso se você não estiver vendo nenhum dado.</string>
</resources> </resources>
+6 -5
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Режим мониторинга</string> <string name="settings_monitor_mode_label">Режим мониторинга</string>
<string name="settings_monitor_mode_description">При каких условиях приложение отслеживает данные Bluetooth.</string> <string name="settings_monitor_mode_description">При каких условиях приложение отслеживает данные Bluetooth.</string>
<string name="settings_scanner_mode_label">Режим сканера</string> <string name="settings_scanner_mode_label">Режим сканера</string>
<string name="settings_scanner_mode_description">Какой режим должен использовать сканер Bluetooth Low Energy - производительность или экономию энергии?</string> <string name="settings_scanner_mode_description">Какой режим должен по умолчанию использовать сканер данных Bluetooth Low Energy - производительность или экономию энергии?</string>
<string name="settings_monitor_mode_manual_label">Когда приложение открыто</string> <string name="settings_monitor_mode_manual_label">Когда приложение открыто</string>
<string name="settings_monitor_mode_automatic_label">Когда устройство подключено</string> <string name="settings_monitor_mode_automatic_label">Когда устройство подключено</string>
<string name="settings_monitor_mode_always_label">Всегда</string> <string name="settings_monitor_mode_always_label">Всегда</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Сбалансированный</string> <string name="settings_scanner_mode_balanced_label">Сбалансированный</string>
<string name="settings_scanner_mode_lowlatency_label">Малая задержка</string> <string name="settings_scanner_mode_lowlatency_label">Малая задержка</string>
<string name="settings_autopause_label">Автопауза</string> <string name="settings_autopause_label">Автопауза</string>
<string name="settings_autopause_description">Приостановка музыки при удалении устройства из уха.</string> <string name="settings_autopause_description">Приостановка аудио при удалении устройства из уха.</string>
<string name="settings_showall_label">Показать все устройства</string> <string name="settings_showall_label">Показать все устройства</string>
<string name="settings_showall_description">Показать находящиеся рядом с Вами устройства других людей.</string> <string name="settings_showall_description">Показать находящиеся рядом с Вами устройства других людей.</string>
<string name="settings_autopplay_label">Автовоспроизведение</string> <string name="settings_autopplay_label">Автовоспроизведение</string>
<string name="settings_autoplay_description">Запуск музыки при вставке наушников.</string> <string name="settings_autoplay_description">Включение воспроизведения аудио при начале использования устройства.</string>
<string name="settings_fake_data_label">Пустые данные</string> <string name="settings_fake_data_label">Пустые данные</string>
<string name="settings_fake_data_description">Показывать пустые данные, например, симулировать отсутствие устройства.</string> <string name="settings_fake_data_description">Показывать пустые данные, например, симулировать устройства, которые не существуют.</string>
<string name="settings_debug_label">Настройки отладки</string> <string name="settings_debug_label">Настройки отладки</string>
<string name="settings_debug_description">Дополнительные настройки для решения проблем с помощью приложения.</string> <string name="settings_debug_description">Дополнительные настройки для решения проблем с помощью приложения.</string>
<string name="settings_signal_minimum_label">Минимальное качество сигнала</string> <string name="settings_signal_minimum_label">Минимальное качество сигнала</string>
@@ -119,7 +119,6 @@
<string name="upgrade_capod_description">Получите дополнительные функции и поддержите разработчика.</string> <string name="upgrade_capod_description">Получите дополнительные функции и поддержите разработчика.</string>
<string name="settings_popup_caseopen_label">Всплывающие окна</string> <string name="settings_popup_caseopen_label">Всплывающие окна</string>
<string name="settings_popup_caseopen_description">Показывать всплывающее окно, когда футляр открыт (эксперимент).</string> <string name="settings_popup_caseopen_description">Показывать всплывающее окно, когда футляр открыт (эксперимент).</string>
<string name="notification_channel_reaction_popup_label">Всплывающие реакции устройства</string>
<string name="overview_bluetooth_disabled_label">Bluetooth отключен</string> <string name="overview_bluetooth_disabled_label">Bluetooth отключен</string>
<string name="overview_bluetooth_disabled_description">Bluetooth отключен, включите его ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth отключен, включите его ;)</string>
<string name="help_translate_label">Перевод</string> <string name="help_translate_label">Перевод</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Нефильтрованные данные BLE</string> <string name="settings_blescanner_unfiltered_label">Нефильтрованные данные BLE</string>
<string name="settings_blescanner_unfiltered_description">Удалите все фильтры из сканера BLE, чтобы показать все переданные данные BLE. Может помочь при добавлении поддержки новых типов наушников.</string> <string name="settings_blescanner_unfiltered_description">Удалите все фильтры из сканера BLE, чтобы показать все переданные данные BLE. Может помочь при добавлении поддержки новых типов наушников.</string>
<string name="permission_required_title">Требуется следующее разрешение:</string> <string name="permission_required_title">Требуется следующее разрешение:</string>
<string name="settings_compatibility_mode_label">Режим совместимости</string>
<string name="settings_compatibility_mode_description">Отключите оптимизацию для улучшения совместимости. Попробуйте это, если не видите данных.</string>
</resources> </resources>
+5 -4
View File
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Vyvážený</string> <string name="settings_scanner_mode_balanced_label">Vyvážený</string>
<string name="settings_scanner_mode_lowlatency_label">Nízka latencia</string> <string name="settings_scanner_mode_lowlatency_label">Nízka latencia</string>
<string name="settings_autopause_label">Automatické pozastavenie</string> <string name="settings_autopause_label">Automatické pozastavenie</string>
<string name="settings_autopause_description">Pozastavte hudbu, keď si vyberiete zariadenie z ucha.</string> <string name="settings_autopause_description">Pozastavte zvuk, keď si vyberiete zariadenie z ucha.</string>
<string name="settings_showall_label">Zobraziť všetky zariadenia</string> <string name="settings_showall_label">Zobraziť všetky zariadenia</string>
<string name="settings_showall_description">Ukázať zariadenia iných ľudí, ktoré sú vo vašej blízkosti.</string> <string name="settings_showall_description">Ukázať zariadenia iných ľudí, ktoré sú vo vašej blízkosti.</string>
<string name="settings_autopplay_label">Automatické prehrávanie</string> <string name="settings_autopplay_label">Automatické prehrávanie</string>
<string name="settings_autoplay_description">Spustiť prehrávanie hudby počas nosenia zariadenia.</string> <string name="settings_autoplay_description">Spustite prehrávanie zvuku, keď je zariadenie nosené.</string>
<string name="settings_fake_data_label">Falošné údaje</string> <string name="settings_fake_data_label">Falošné údaje</string>
<string name="settings_fake_data_description">Zobrazovať falošné údaje, t. j. simulovať neexistujúce zariadenie.</string> <string name="settings_fake_data_description">Zobrazovať falošné údaje, t. j. simulovať neexistujúce zariadenia.</string>
<string name="settings_debug_label">Nastavenia ladenia</string> <string name="settings_debug_label">Nastavenia ladenia</string>
<string name="settings_debug_description">Ďalšie nastavenia na pomoc pri riešení problémov s aplikáciou.</string> <string name="settings_debug_description">Ďalšie nastavenia na pomoc pri riešení problémov s aplikáciou.</string>
<string name="settings_signal_minimum_label">Minimálna kvalita signálu</string> <string name="settings_signal_minimum_label">Minimálna kvalita signálu</string>
@@ -119,7 +119,6 @@
<string name="upgrade_capod_description">Získajte ďalšie funkcie a podporte vývojára.</string> <string name="upgrade_capod_description">Získajte ďalšie funkcie a podporte vývojára.</string>
<string name="settings_popup_caseopen_label">Zobraziť kontextové okno</string> <string name="settings_popup_caseopen_label">Zobraziť kontextové okno</string>
<string name="settings_popup_caseopen_description">Po otvorení puzdra zariadenia zobraziť kontextové okno (experimentálne).</string> <string name="settings_popup_caseopen_description">Po otvorení puzdra zariadenia zobraziť kontextové okno (experimentálne).</string>
<string name="notification_channel_reaction_popup_label">Kontextové okno reakcií zariadenia</string>
<string name="overview_bluetooth_disabled_label">Bluetooth je vypnuté</string> <string name="overview_bluetooth_disabled_label">Bluetooth je vypnuté</string>
<string name="overview_bluetooth_disabled_description">Bluetooth je vypnuté, zapnite ho ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth je vypnuté, zapnite ho ;)</string>
<string name="help_translate_label">Preklad</string> <string name="help_translate_label">Preklad</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Nefiltrované údaje BLE</string> <string name="settings_blescanner_unfiltered_label">Nefiltrované údaje BLE</string>
<string name="settings_blescanner_unfiltered_description">Odstráňte všetky filtre zo skenera BLE, aby sa zobrazili všetky vysielané údaje BLE. Užitočné na pridanie podpory pre nové typy slúchadiel.</string> <string name="settings_blescanner_unfiltered_description">Odstráňte všetky filtre zo skenera BLE, aby sa zobrazili všetky vysielané údaje BLE. Užitočné na pridanie podpory pre nové typy slúchadiel.</string>
<string name="permission_required_title">Vyžaduje sa nasledujúce povolenie:</string> <string name="permission_required_title">Vyžaduje sa nasledujúce povolenie:</string>
<string name="settings_compatibility_mode_label">Režim kompatibility</string>
<string name="settings_compatibility_mode_description">Zakázať optimalizáciu na zlepšenie kompatibility. Skúste to, ak nevidíte žiadne údaje.</string>
</resources> </resources>
+62 -2
View File
@@ -50,6 +50,56 @@
<string name="pods_charging_label">Doluyor</string> <string name="pods_charging_label">Doluyor</string>
<string name="pods_inear_label">Kulakta</string> <string name="pods_inear_label">Kulakta</string>
<string name="pods_microphone_label">Mikrofon</string> <string name="pods_microphone_label">Mikrofon</string>
<string name="pods_yours">Senin</string>
<string name="headset_being_worn_label">Giyilmek</string>
<string name="pods_case_unknown_state">Bilinmeyen durum</string>
<string name="overview_nomaindevice_label">Birincil aygıt yok</string>
<string name="overview_nomaindevice_description">Algılanan tüm cihazların sizin olması olası değildir. Cihazınızı açın ve bağlayın veya ayarları yapın.</string>
<string name="settings_label">Ayarlar</string>
<string name="settings_privacy_policy_label">Gizlilik ilkesi</string>
<string name="settings_privacy_policy_desc">Verileri sorumlu bir şekilde işle.</string>
<string name="settings_licenses_label">Lisans</string>
<string name="settings_category_other_label">Diğer</string>
<string name="settings_general_label">Ayarlar</string>
<string name="settings_general_description">Tüm uygulamayı etkileyen genel düzenlemeler.</string>
<string name="settings_acknowledgements_label">Teşekkür</string>
<string name="changelog_label">Değişiklik Günlüğü</string>
<string name="settings_support_email_developer_label">E-posta geliştiricisi</string>
<string name="settings_support_installid_label">Yükleme Kimliği</string>
<string name="settings_support_installid_desc">Otomatik hata raporları anonimdir. Geliştiricinin hata raporlarınızı bulması gerekiyorsa yükleme kimliğinizi paylaşın.</string>
<string name="settings_support_label">Destek</string>
<string name="settings_support_description">Yardıma ihtiyacın olursa.</string>
<string name="issue_tracker_label">Sorun izleyicisi</string>
<string name="issue_tracker_description">Hata raporları ve özellik istekleri için genel bir sorun izleyicisi (yalnızca İngilizce).</string>
<string name="discord_label">Discord</string>
<string name="discord_description">Takılıp soru sormak için bir yer.</string>
<string name="settings_support_email_developer_description">Yalnızca Almanca veya İngilizce yanıt verebildiğimi unutmayın.</string>
<string name="settings_debug_autoreports_label">Otomatik hata raporları</string>
<string name="settings_debug_autoreports_description">Sorunları otomatik olarak bildirir, örneğin bir uygulama çökmesiyle ilgili ayrıntılar, böylece nasıl düzelteceğimi bulabilirim.</string>
<string name="settings_debug_mode_label">Hata ayıklama modu</string>
<string name="settings_debug_mode_description">Sorunları gidermek için ek bilgiler gösterin.</string>
<string name="settings_monitor_mode_label">İzleme modu</string>
<string name="settings_monitor_mode_description">Bu uygulama hangi koşullar altında Bluetooth verilerini izler.</string>
<string name="settings_scanner_mode_label">Tarama modu</string>
<string name="settings_scanner_mode_description">Bluetooth Düşük Enerjili veri tarayıcısı performansa öncelik vermeli mi yoksa enerji tasarrufu mu yapmalı?</string>
<string name="settings_monitor_mode_manual_label">Uygulama açıkken</string>
<string name="settings_monitor_mode_automatic_label">Aygıt bağlandığında</string>
<string name="settings_monitor_mode_always_label">Her zaman</string>
<string name="settings_scanner_mode_lowpower_label">Düşük güç</string>
<string name="settings_scanner_mode_balanced_label">Dengeli</string>
<string name="settings_scanner_mode_lowlatency_label">Düşük gecikme süresi</string>
<string name="settings_autopause_label">Otomatik duraklama</string>
<string name="settings_autopause_description">Cihazı kulağınızdan çıkarırken sesi duraklatın.</string>
<string name="settings_showall_label">Tüm aygıtları göster</string>
<string name="settings_showall_description">Yakınınızda bulunan diğer kişilerin cihazlarını gösterin.</string>
<string name="settings_autopplay_label">Otomatik oynatma</string>
<string name="settings_autoplay_description">Cihaz takıldığında ses çalmayı başlatın.</string>
<string name="settings_fake_data_label">Sahte veriler</string>
<string name="settings_fake_data_description">Sahte verileri göster, yani varolmayan cihazları simüle et.</string>
<string name="settings_debug_label">Hata ayıklama ayarları</string>
<string name="settings_debug_description">Uygulamayla ilgili sorunları gidermeye yardımcı olacak ek ayarlar.</string>
<string name="settings_signal_minimum_label">Minimum sinyal kalitesi</string>
<string name="settings_signal_minimum_description">Bir cihazın sahip olması gereken minimum sinyal kalitesi size ait olarak kabul edilmelidir.</string>
<string name="settings_autoconnect_label">Otomatik bağlantı</string> <string name="settings_autoconnect_label">Otomatik bağlantı</string>
<string name="settings_autoconnect_description">Android otomatik olarak bağlanmazsa, biz de sorabiliriz. Bu, monitör modu ayarını \'Her zaman\' olarak ayarlayacaktır.</string> <string name="settings_autoconnect_description">Android otomatik olarak bağlanmazsa, biz de sorabiliriz. Bu, monitör modu ayarını \'Her zaman\' olarak ayarlayacaktır.</string>
<string name="settings_autoconnect_condition_label">Otomatik bağlantı koşulu</string> <string name="settings_autoconnect_condition_label">Otomatik bağlantı koşulu</string>
@@ -69,9 +119,19 @@
<string name="upgrade_capod_description">Ek özellikler edinin ve geliştiriciyi destekleyin.</string> <string name="upgrade_capod_description">Ek özellikler edinin ve geliştiriciyi destekleyin.</string>
<string name="settings_popup_caseopen_label">Pop-up\'ı göster</string> <string name="settings_popup_caseopen_label">Pop-up\'ı göster</string>
<string name="settings_popup_caseopen_description">Cihaz kasası açıldığında bir açılır pencere göster (deneysel).</string> <string name="settings_popup_caseopen_description">Cihaz kasası açıldığında bir açılır pencere göster (deneysel).</string>
<string name="notification_channel_reaction_popup_label">Pop-up cihaz reaksiyonları</string>
<string name="overview_bluetooth_disabled_label">Bluetooth devre dışı</string> <string name="overview_bluetooth_disabled_label">Bluetooth devre dışı</string>
<string name="overview_bluetooth_disabled_description">Bluetooth devre dışı, etkinleştirin ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth devre dışı, etkinleştirin ;)</string>
<string name="help_translate_label">Tercüme</string> <string name="help_translate_label">Tercüme</string>
<string name="help_translate_description">Bunu en sevdiğiniz dile çevirmeye yardım edin.</string> <string name="help_translate_description">Bu uygulamayı en sevdiğiniz dile çevirmeye yardımcı olun.</string>
<string name="settings_onepod_mode_label">Tek bölme modu</string>
<string name="settings_onepod_mode_description">Her iki bölmeyi de takmak gerekli değildir, tek bir pod takmak reaksiyonları tetiklemek için yeterlidir.</string>
<string name="permission_system_alert_window_label">Sistem Uyarı Penceresi</string>
<string name="permission_system_alert_window_description">CAPod\'un \"PopUp\'ı Göster\" özelliğini mümkün kılmak için diğer uygulamaların üzerinde çizmesine izin verin.</string>
<string name="last_seen_x">Son görülme: %s</string>
<string name="first_seen_x">İlk görülme: %s</string>
<string name="settings_blescanner_unfiltered_label">Filtrelenmemiş BLE verileri</string>
<string name="settings_blescanner_unfiltered_description">Yayınlanan tüm BLE verilerini göstermek için BLE tarayıcısından tüm filtreleri kaldırın. Yeni kulaklık türlerine destek eklemek için kullanışlıdır.</string>
<string name="permission_required_title">Aşağıdaki izin gereklidir:</string>
<string name="settings_compatibility_mode_label">Uyumluluk modu</string>
<string name="settings_compatibility_mode_description">Uyumluluğu artırmak için iyileştirmeleri devre dışı bırakın. Herhangi bir veri görmüyorsanız bunu deneyin.</string>
</resources> </resources>
-1
View File
@@ -76,7 +76,6 @@
<string name="overview_bluetooth_disabled_label">Bluetooth вимкнено</string> <string name="overview_bluetooth_disabled_label">Bluetooth вимкнено</string>
<string name="overview_bluetooth_disabled_description">Bluetooth вимкнено, увімкніть його ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth вимкнено, увімкніть його ;)</string>
<string name="help_translate_label">Переклад</string> <string name="help_translate_label">Переклад</string>
<string name="help_translate_description">Допоможіть перекласти це своєю улюбленою мовою.</string>
<string name="settings_onepod_mode_label">Режим одного навушника</string> <string name="settings_onepod_mode_label">Режим одного навушника</string>
<string name="settings_onepod_mode_description">Одягання обох навушників не є необхідним, одягання одного навушника цілком достатньо для запуску реагування.</string> <string name="settings_onepod_mode_description">Одягання обох навушників не є необхідним, одягання одного навушника цілком достатньо для запуску реагування.</string>
<string name="permission_system_alert_window_label">Вікно системного повідомлення</string> <string name="permission_system_alert_window_label">Вікно системного повідомлення</string>
+7 -6
View File
@@ -81,7 +81,7 @@
<string name="settings_monitor_mode_label">Chế độ giám sát</string> <string name="settings_monitor_mode_label">Chế độ giám sát</string>
<string name="settings_monitor_mode_description">Trong trường hợp nào ứng dụng này giám sát dữ liệu Bluetooth.</string> <string name="settings_monitor_mode_description">Trong trường hợp nào ứng dụng này giám sát dữ liệu Bluetooth.</string>
<string name="settings_scanner_mode_label">Chế độ quét</string> <string name="settings_scanner_mode_label">Chế độ quét</string>
<string name="settings_scanner_mode_description">Máy quét Bluetooth Low Energy nên ưu tiên hiệu suất hay tiết kiệm năng lượng?</string> <string name="settings_scanner_mode_description">Máy quét dữ liệu Bluetooth Low Energy nên ưu tiên hiệu suất hay tiết kiệm năng lượng?</string>
<string name="settings_monitor_mode_manual_label">Khi ứng dụng được mở</string> <string name="settings_monitor_mode_manual_label">Khi ứng dụng được mở</string>
<string name="settings_monitor_mode_automatic_label">Khi thiết bị được kết nối</string> <string name="settings_monitor_mode_automatic_label">Khi thiết bị được kết nối</string>
<string name="settings_monitor_mode_always_label">Luôn luôn</string> <string name="settings_monitor_mode_always_label">Luôn luôn</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">Cân bằng</string> <string name="settings_scanner_mode_balanced_label">Cân bằng</string>
<string name="settings_scanner_mode_lowlatency_label">Độ trễ thấp</string> <string name="settings_scanner_mode_lowlatency_label">Độ trễ thấp</string>
<string name="settings_autopause_label">Tự động tạm dừng</string> <string name="settings_autopause_label">Tự động tạm dừng</string>
<string name="settings_autopause_description">Tạm dừng nhạc khi tháo thiết bị ra khỏi tai.</string> <string name="settings_autopause_description">Tạm dừng âm thanh khi tháo thiết bị khỏi tai bạn.</string>
<string name="settings_showall_label">Hiển thị tất cả các thiết bị</string> <string name="settings_showall_label">Hiển thị tất cả các thiết bị</string>
<string name="settings_showall_description">Hiển thị thiết bị của người khác ở gần bạn.</string> <string name="settings_showall_description">Hiển thị thiết bị của người khác ở gần bạn.</string>
<string name="settings_autopplay_label">Tự động phát</string> <string name="settings_autopplay_label">Tự động phát</string>
<string name="settings_autoplay_description">Bắt đầu phát nhạc khi đeo thiết bị.</string> <string name="settings_autoplay_description">Bắt đầu phát lại âm thanh khi thiết bị được đeo.</string>
<string name="settings_fake_data_label">Dữ liệu giả</string> <string name="settings_fake_data_label">Dữ liệu giả</string>
<string name="settings_fake_data_description">Hiển thị dữ liệu giả mạo, tức là mô phỏng thiết bị không tồn tại.</string> <string name="settings_fake_data_description">Hiển thị dữ liệu giả, tức là mô phỏng các thiết bị không tồn tại.</string>
<string name="settings_debug_label">Cài đặt gỡ lỗi</string> <string name="settings_debug_label">Cài đặt gỡ lỗi</string>
<string name="settings_debug_description">Cài đặt bổ sung để giúp khắc phục sự cố với ứng dụng.</string> <string name="settings_debug_description">Cài đặt bổ sung để giúp khắc phục sự cố với ứng dụng.</string>
<string name="settings_signal_minimum_label">Chất lượng tín hiệu tối thiểu</string> <string name="settings_signal_minimum_label">Chất lượng tín hiệu tối thiểu</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">Nhận các tính năng bổ sung và hỗ trợ nhà phát triển.</string> <string name="upgrade_capod_description">Nhận các tính năng bổ sung và hỗ trợ nhà phát triển.</string>
<string name="settings_popup_caseopen_label">Hiển thị popup</string> <string name="settings_popup_caseopen_label">Hiển thị popup</string>
<string name="settings_popup_caseopen_description">Hiển thị cửa sổ bật lên khi hộp thiết bị được mở (thử nghiệm).</string> <string name="settings_popup_caseopen_description">Hiển thị cửa sổ bật lên khi hộp thiết bị được mở (thử nghiệm).</string>
<string name="notification_channel_reaction_popup_label">Popup phản ứng thiết bị</string>
<string name="overview_bluetooth_disabled_label">Bluetooth bị tắt</string> <string name="overview_bluetooth_disabled_label">Bluetooth bị tắt</string>
<string name="overview_bluetooth_disabled_description">Bluetooth bị tắt, hãy bật nó lên ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth bị tắt, hãy bật nó lên ;)</string>
<string name="help_translate_label">Dịch</string> <string name="help_translate_label">Dịch</string>
<string name="help_translate_description">Giúp dịch điều này sang ngôn ngữ yêu thích của bạn.</string> <string name="help_translate_description">Giúp dịch ứng dụng này sang ngôn ngữ yêu thích của bạn.</string>
<string name="settings_onepod_mode_label">Chế độ 1 tai nghe</string> <string name="settings_onepod_mode_label">Chế độ 1 tai nghe</string>
<string name="settings_onepod_mode_description">Không cần đeo cả hai, chỉ đeo một tai nghe là đủ để kích hoạt phản ứng.</string> <string name="settings_onepod_mode_description">Không cần đeo cả hai, chỉ đeo một tai nghe là đủ để kích hoạt phản ứng.</string>
<string name="permission_system_alert_window_label">Cửa sổ cảnh báo hệ thống</string> <string name="permission_system_alert_window_label">Cửa sổ cảnh báo hệ thống</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">Dữ liệu BLE chưa được lọc</string> <string name="settings_blescanner_unfiltered_label">Dữ liệu BLE chưa được lọc</string>
<string name="settings_blescanner_unfiltered_description">Xóa mọi bộ lọc khỏi máy quét BLE để hiển thị tất cả dữ liệu BLE đã phát. Hữu ích để thêm hỗ trợ cho các loại tai nghe mới.</string> <string name="settings_blescanner_unfiltered_description">Xóa mọi bộ lọc khỏi máy quét BLE để hiển thị tất cả dữ liệu BLE đã phát. Hữu ích để thêm hỗ trợ cho các loại tai nghe mới.</string>
<string name="permission_required_title">Quyền sau đây là bắt buộc:</string> <string name="permission_required_title">Quyền sau đây là bắt buộc:</string>
<string name="settings_compatibility_mode_label">Chế độ tương thích</string>
<string name="settings_compatibility_mode_description">Tắt tối ưu hóa để cải thiện khả năng tương thích. Hãy thử điều này nếu bạn không thấy bất kỳ dữ liệu nào.</string>
</resources> </resources>
+10 -9
View File
@@ -26,7 +26,7 @@
<string name="permission_bluetooth_label">蓝牙</string> <string name="permission_bluetooth_label">蓝牙</string>
<string name="permission_bluetooth_description">本应用需要“蓝牙”权限才能连接已配对的蓝牙设备</string> <string name="permission_bluetooth_description">本应用需要“蓝牙”权限才能连接已配对的蓝牙设备</string>
<string name="permission_access_fine_location_label">访问精准位置</string> <string name="permission_access_fine_location_label">访问精准位置</string>
<string name="permission_access_fine_location_description">CAPod 使用“精准定位”权限来接收低功耗蓝牙数据。您的耳机使用低功耗蓝牙技术来播其状态,本应用「不会」通过蓝牙数据来给您定位</string> <string name="permission_access_fine_location_description">CAPod 使用“精准定位”权限来接收低功耗蓝牙数据。您的耳机使用低功耗蓝牙技术来广播其状态,本应用「不会」通过蓝牙数据测定您的位置</string>
<string name="permission_background_location_label">在后台访问位置</string> <string name="permission_background_location_label">在后台访问位置</string>
<string name="permission_background_location_description">CAPod 使用“在后台访问位置”权限以在本应用被关闭时继续提供如“显示弹窗”、“自动连接”等功能。此权限允许本应用在后台运行时继续接收蓝牙低功耗数据。本应用并不使用蓝牙数据来窥探您的位置。</string> <string name="permission_background_location_description">CAPod 使用“在后台访问位置”权限以在本应用被关闭时继续提供如“显示弹窗”、“自动连接”等功能。此权限允许本应用在后台运行时继续接收蓝牙低功耗数据。本应用并不使用蓝牙数据来窥探您的位置。</string>
<string name="permission_ignore_battery_optimizations_label">禁用电池优化</string> <string name="permission_ignore_battery_optimizations_label">禁用电池优化</string>
@@ -79,9 +79,9 @@
<string name="settings_debug_mode_label">调试模式</string> <string name="settings_debug_mode_label">调试模式</string>
<string name="settings_debug_mode_description">显示额外信息以帮助调试故障。</string> <string name="settings_debug_mode_description">显示额外信息以帮助调试故障。</string>
<string name="settings_monitor_mode_label">监控模式</string> <string name="settings_monitor_mode_label">监控模式</string>
<string name="settings_monitor_mode_description">此模式下本应用将监视蓝牙数据。</string> <string name="settings_monitor_mode_description">决定本应用在何时收听蓝牙数据。</string>
<string name="settings_scanner_mode_label">扫描模式</string> <string name="settings_scanner_mode_label">扫描模式</string>
<string name="settings_scanner_mode_description">低功耗蓝牙扫描器应着重性能还是省电?</string> <string name="settings_scanner_mode_description">低功耗蓝牙数据扫描器应着重性能还是省电?</string>
<string name="settings_monitor_mode_manual_label">应用打开时</string> <string name="settings_monitor_mode_manual_label">应用打开时</string>
<string name="settings_monitor_mode_automatic_label">设备连接时</string> <string name="settings_monitor_mode_automatic_label">设备连接时</string>
<string name="settings_monitor_mode_always_label">始终</string> <string name="settings_monitor_mode_always_label">始终</string>
@@ -89,13 +89,13 @@
<string name="settings_scanner_mode_balanced_label">平衡</string> <string name="settings_scanner_mode_balanced_label">平衡</string>
<string name="settings_scanner_mode_lowlatency_label">低延迟</string> <string name="settings_scanner_mode_lowlatency_label">低延迟</string>
<string name="settings_autopause_label">自动暂停</string> <string name="settings_autopause_label">自动暂停</string>
<string name="settings_autopause_description">从耳中取出时自动暂停音播放</string> <string name="settings_autopause_description">从耳中取出时自动暂停音播放</string>
<string name="settings_showall_label">显示所有设备</string> <string name="settings_showall_label">显示所有设备</string>
<string name="settings_showall_description">显示您附近的其他人的设备</string> <string name="settings_showall_description">显示您附近的其他人的设备</string>
<string name="settings_autopplay_label">自动播放</string> <string name="settings_autopplay_label">自动播放</string>
<string name="settings_autoplay_description">佩戴设备时自动开始播放音乐。</string> <string name="settings_autoplay_description">戴在耳上时自动开始音频播放</string>
<string name="settings_fake_data_label">假数据</string> <string name="settings_fake_data_label">假数据</string>
<string name="settings_fake_data_description">显示伪造的数据,模拟不存在的设备</string> <string name="settings_fake_data_description">显示伪造的数据,模拟不存在的设备</string>
<string name="settings_debug_label">调试设置</string> <string name="settings_debug_label">调试设置</string>
<string name="settings_debug_description">帮助解决应用程序问题的其他设置</string> <string name="settings_debug_description">帮助解决应用程序问题的其他设置</string>
<string name="settings_signal_minimum_label">最低信号质量</string> <string name="settings_signal_minimum_label">最低信号质量</string>
@@ -119,11 +119,10 @@
<string name="upgrade_capod_description">享用额外的功能并支持开发者。</string> <string name="upgrade_capod_description">享用额外的功能并支持开发者。</string>
<string name="settings_popup_caseopen_label">显示弹窗</string> <string name="settings_popup_caseopen_label">显示弹窗</string>
<string name="settings_popup_caseopen_description">设备充电仓打开时显示弹窗(实验性)</string> <string name="settings_popup_caseopen_description">设备充电仓打开时显示弹窗(实验性)</string>
<string name="notification_channel_reaction_popup_label">设备弹窗动作</string>
<string name="overview_bluetooth_disabled_label">蓝牙已禁用</string> <string name="overview_bluetooth_disabled_label">蓝牙已禁用</string>
<string name="overview_bluetooth_disabled_description">蓝牙已关闭,请启用之 ;)</string> <string name="overview_bluetooth_disabled_description">蓝牙已关闭,请启 ;)</string>
<string name="help_translate_label">翻译</string> <string name="help_translate_label">翻译</string>
<string name="help_translate_description">您可以来翻译本应用</string> <string name="help_translate_description">帮助翻译本应用</string>
<string name="settings_onepod_mode_label">单耳模式</string> <string name="settings_onepod_mode_label">单耳模式</string>
<string name="settings_onepod_mode_description">不需要同时佩戴两支耳机,单支即可引发反应</string> <string name="settings_onepod_mode_description">不需要同时佩戴两支耳机,单支即可引发反应</string>
<string name="permission_system_alert_window_label">系统警告窗口</string> <string name="permission_system_alert_window_label">系统警告窗口</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">未经过滤的 BLE 数据</string> <string name="settings_blescanner_unfiltered_label">未经过滤的 BLE 数据</string>
<string name="settings_blescanner_unfiltered_description">完全解除蓝牙低功耗(BLE)扫描器上的过滤器,以显示被广播的全部 BLE 数据。可用于了解和新增更多耳机型号的支持。</string> <string name="settings_blescanner_unfiltered_description">完全解除蓝牙低功耗(BLE)扫描器上的过滤器,以显示被广播的全部 BLE 数据。可用于了解和新增更多耳机型号的支持。</string>
<string name="permission_required_title">需要下列权限:</string> <string name="permission_required_title">需要下列权限:</string>
<string name="settings_compatibility_mode_label">兼容模式</string>
<string name="settings_compatibility_mode_description">禁用优化以提高兼容性,请在未看到任何数据时尝试此操作</string>
</resources> </resources>
+6 -5
View File
@@ -68,7 +68,7 @@
<string name="settings_support_installid_label">安裝 ID</string> <string name="settings_support_installid_label">安裝 ID</string>
<string name="settings_support_installid_desc">自動傳送的錯誤報告是匿名的。如果開發人員需要找出你的錯誤報告將分享你的安裝 ID。</string> <string name="settings_support_installid_desc">自動傳送的錯誤報告是匿名的。如果開發人員需要找出你的錯誤報告將分享你的安裝 ID。</string>
<string name="settings_support_label">支援</string> <string name="settings_support_label">支援</string>
<string name="settings_support_description">如果你需要助。</string> <string name="settings_support_description">如果你需要助。</string>
<string name="issue_tracker_label">問題追蹤器</string> <string name="issue_tracker_label">問題追蹤器</string>
<string name="issue_tracker_description">一個用於錯誤回報和功能需求的公用問題追蹤器 (僅英文)。</string> <string name="issue_tracker_description">一個用於錯誤回報和功能需求的公用問題追蹤器 (僅英文)。</string>
<string name="discord_label">Discord</string> <string name="discord_label">Discord</string>
@@ -93,11 +93,11 @@
<string name="settings_showall_label">顯示所有裝置</string> <string name="settings_showall_label">顯示所有裝置</string>
<string name="settings_showall_description">顯示附近其他人的裝置</string> <string name="settings_showall_description">顯示附近其他人的裝置</string>
<string name="settings_autopplay_label">自動播放</string> <string name="settings_autopplay_label">自動播放</string>
<string name="settings_autoplay_description">佩戴時自動播放</string> <string name="settings_autoplay_description">佩戴到耳上時自動播放</string>
<string name="settings_fake_data_label">假資料</string> <string name="settings_fake_data_label">假資料</string>
<string name="settings_fake_data_description">顯示假資料,模擬不存在的裝置。</string> <string name="settings_fake_data_description">顯示假資料,模擬不存在的裝置。</string>
<string name="settings_debug_label">偵錯設定</string> <string name="settings_debug_label">偵錯設定</string>
<string name="settings_debug_description">一個能助這個應用程式故障檢修的附加設定。</string> <string name="settings_debug_description">一個能助這個應用程式故障檢修的附加設定。</string>
<string name="settings_signal_minimum_label">最低訊號質量</string> <string name="settings_signal_minimum_label">最低訊號質量</string>
<string name="settings_signal_minimum_description">可以被認為是你的裝置的最低訊號質量。</string> <string name="settings_signal_minimum_description">可以被認為是你的裝置的最低訊號質量。</string>
<string name="settings_autoconnect_label">自動連線</string> <string name="settings_autoconnect_label">自動連線</string>
@@ -111,7 +111,7 @@
<string name="settings_maindevice_address_description">你的已配對裝置的位址。這個應用程式用該位址來確定何時連線到你的手機。</string> <string name="settings_maindevice_address_description">你的已配對裝置的位址。這個應用程式用該位址來確定何時連線到你的手機。</string>
<string name="settings_maindevice_address_none"></string> <string name="settings_maindevice_address_none"></string>
<string name="settings_maindevice_model_label">你的裝置型號</string> <string name="settings_maindevice_model_label">你的裝置型號</string>
<string name="settings_maindevice_model_description">你的主要裝置型號。這能助這個應用程式在未連線到你的手機時辨識你的裝置。</string> <string name="settings_maindevice_model_description">你的主要裝置型號。這能助這個應用程式在未連線到你的手機時辨識你的裝置。</string>
<string name="settings_reaction_autoconnect_whenseen_label">看到時</string> <string name="settings_reaction_autoconnect_whenseen_label">看到時</string>
<string name="settings_reaction_autoconnect_caseopen_label">充電盒開啟</string> <string name="settings_reaction_autoconnect_caseopen_label">充電盒開啟</string>
<string name="settings_reaction_autoconnect_inear_label">在耳中</string> <string name="settings_reaction_autoconnect_inear_label">在耳中</string>
@@ -119,7 +119,6 @@
<string name="upgrade_capod_description">取得附加功能並支持開發人員。</string> <string name="upgrade_capod_description">取得附加功能並支持開發人員。</string>
<string name="settings_popup_caseopen_label">顯示彈出式視窗</string> <string name="settings_popup_caseopen_label">顯示彈出式視窗</string>
<string name="settings_popup_caseopen_description">充電盒開啟時顯示彈出式視窗 (實驗性)</string> <string name="settings_popup_caseopen_description">充電盒開啟時顯示彈出式視窗 (實驗性)</string>
<string name="notification_channel_reaction_popup_label">彈出式視窗裝置反應</string>
<string name="overview_bluetooth_disabled_label">藍牙已停用</string> <string name="overview_bluetooth_disabled_label">藍牙已停用</string>
<string name="overview_bluetooth_disabled_description">藍牙已停用,啟用它 ;)</string> <string name="overview_bluetooth_disabled_description">藍牙已停用,啟用它 ;)</string>
<string name="help_translate_label">翻譯</string> <string name="help_translate_label">翻譯</string>
@@ -133,4 +132,6 @@
<string name="settings_blescanner_unfiltered_label">未過濾的低功耗藍牙資料</string> <string name="settings_blescanner_unfiltered_label">未過濾的低功耗藍牙資料</string>
<string name="settings_blescanner_unfiltered_description">移除低功耗藍牙掃描器的任何過濾器,以顯示所有廣播的低功耗藍牙資料。對增加新耳機類型的支援很有用。</string> <string name="settings_blescanner_unfiltered_description">移除低功耗藍牙掃描器的任何過濾器,以顯示所有廣播的低功耗藍牙資料。對增加新耳機類型的支援很有用。</string>
<string name="permission_required_title">可能要求下列權限:</string> <string name="permission_required_title">可能要求下列權限:</string>
<string name="settings_compatibility_mode_label">相容模式</string>
<string name="settings_compatibility_mode_description">停用最佳化以提高相容性。請在未看到任何資料時開啟。</string>
</resources> </resources>
+2
View File
@@ -144,4 +144,6 @@
<string name="permission_required_title">The following permission is required:</string> <string name="permission_required_title">The following permission is required:</string>
<string name="settings_compatibility_mode_label">Compatibility mode</string> <string name="settings_compatibility_mode_label">Compatibility mode</string>
<string name="settings_compatibility_mode_description">Disable optimizations to improve compatibility. Try this if you are not seeing any data.</string> <string name="settings_compatibility_mode_description">Disable optimizations to improve compatibility. Try this if you are not seeing any data.</string>
<string name="translators_thanks_title">Translators</string>
<string name="translators_thanks_description">darken</string>
</resources> </resources>
@@ -4,6 +4,15 @@
<PreferenceCategory <PreferenceCategory
android:title="@string/general_thank_you_label" android:title="@string/general_thank_you_label"
app:iconSpaceReserved="false"> app:iconSpaceReserved="false">
<Preference
android:key="thanks.translators"
android:summary="@string/translators_thanks_description"
android:title="@string/translators_thanks_title"
app:iconSpaceReserved="false">
<intent
android:action="android.intent.action.VIEW"
android:data="https://crowdin.com/project/capod/activity-stream" />
</Preference>
<Preference <Preference
android:key="thanks.maxpatchs" android:key="thanks.maxpatchs"
android:summary="Thanks for the lovely icons." android:summary="Thanks for the lovely icons."
@@ -3,6 +3,7 @@ package eu.darken.capod.pods.core.apple
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.apple.airpods.AirPodsGen1 import eu.darken.capod.pods.core.apple.airpods.AirPodsGen1
import eu.darken.capod.pods.core.apple.airpods.AirPodsPro import eu.darken.capod.pods.core.apple.airpods.AirPodsPro
import eu.darken.capod.pods.core.apple.misc.UnknownAppleDevice
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.instanceOf import io.kotest.matchers.types.instanceOf
import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.runBlockingTest
@@ -12,14 +13,14 @@ class AirPodsFactoryTest : BaseAirPodsTest() {
@Test @Test
fun `create AirPodsGen1`() = runBlockingTest { fun `create AirPodsGen1`() = runBlockingTest {
create<DualApplePods>("07 19 01 02 20 55 AA 56 31 00 00 6F E4 DF 10 AF 10 60 81 03 3B 76 D9 C7 11 22 88") { create<DualAirPods>("07 19 01 02 20 55 AA 56 31 00 00 6F E4 DF 10 AF 10 60 81 03 3B 76 D9 C7 11 22 88") {
this shouldBe instanceOf<AirPodsGen1>() this shouldBe instanceOf<AirPodsGen1>()
} }
} }
@Test @Test
fun `create AirPodsPro`() = runBlockingTest { fun `create AirPodsPro`() = runBlockingTest {
create<DualApplePods>("07 19 01 0E 20 2B 99 8F 01 00 >09< 10 30 EE F3 41 B5 D8 9F A3 B0 B4 17 9F 85 97 5F") { create<DualAirPods>("07 19 01 0E 20 2B 99 8F 01 00 >09< 10 30 EE F3 41 B5 D8 9F A3 B0 B4 17 9F 85 97 5F") {
this shouldBe instanceOf<AirPodsPro>() this shouldBe instanceOf<AirPodsPro>()
} }
} }
@@ -8,7 +8,7 @@ class BasicSingleApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test mapping`() = runBlockingTest { fun `test mapping`() = runBlockingTest {
create<BasicSingleApplePods>("07 19 01 05 20 00 F5 0F 01 01 00 6D CE C0 04 22 0A 85 31 2D 82 6B 42 80 01 20 1A") { create<SingleApplePods>("07 19 01 05 20 00 F5 0F 01 01 00 6D CE C0 04 22 0A 85 31 2D 82 6B 42 80 01 20 1A") {
rawPrefix shouldBe 0x01.toUByte() rawPrefix shouldBe 0x01.toUByte()
rawDeviceModel shouldBe 0x0520.toUShort() rawDeviceModel shouldBe 0x0520.toUShort()
rawStatus shouldBe 0x00.toUByte() rawStatus shouldBe 0x00.toUByte()
@@ -23,7 +23,7 @@ class BasicSingleApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test battery headset percent`() = runBlockingTest { fun `test battery headset percent`() = runBlockingTest {
create<BasicSingleApplePods>("07 19 01 05 20 00 F5 0F 01 01 00 6D CE C0 04 22 0A 85 31 2D 82 6B 42 80 01 20 1A") { create<SingleApplePods>("07 19 01 05 20 00 F5 0F 01 01 00 6D CE C0 04 22 0A 85 31 2D 82 6B 42 80 01 20 1A") {
batteryHeadsetPercent shouldBe 0.5f batteryHeadsetPercent shouldBe 0.5f
} }
} }
@@ -8,7 +8,7 @@ class DualApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test bit mapping`() = runBlockingTest { fun `test bit mapping`() = runBlockingTest {
create<DualApplePods>("07 19 01 0E 20 54 AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 54 AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
rawPrefix shouldBe 0x01.toUByte() rawPrefix shouldBe 0x01.toUByte()
rawDeviceModel shouldBe 0x0e20.toUShort() rawDeviceModel shouldBe 0x0e20.toUShort()
@@ -24,13 +24,13 @@ class DualApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test AirPodDevice - active microphone`() = runBlockingTest { fun `test AirPodDevice - active microphone`() = runBlockingTest {
create<DualApplePods>("07 19 01 0E 20 >2B< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >2B< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00101011 // 00101011
// --^----- // --^-----
isLeftPodMicrophone shouldBe true isLeftPodMicrophone shouldBe true
isRightPodMicrophone shouldBe false isRightPodMicrophone shouldBe false
} }
create<DualApplePods>("07 19 01 0E 20 >0B< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >0B< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00001011 // 00001011
// --^----- // --^-----
isLeftPodMicrophone shouldBe false isLeftPodMicrophone shouldBe false
@@ -41,24 +41,24 @@ class DualApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test AirPodDevice - left pod ear status`() = runBlockingTest { fun `test AirPodDevice - left pod ear status`() = runBlockingTest {
// Left Pod primary // Left Pod primary
create<DualApplePods>("07 19 01 0E 20 >22< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >22< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00100010 // 00100010
// 765432¹0 // 765432¹0
isLeftPodInEar shouldBe true isLeftPodInEar shouldBe true
} }
create<DualApplePods>("07 19 01 0E 20 >20< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >20< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00100000 // 00100000
// 765432¹0 // 765432¹0
isLeftPodInEar shouldBe false isLeftPodInEar shouldBe false
} }
// Right Pod is primary // Right Pod is primary
create<DualApplePods>("07 19 01 0E 20 >09< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >09< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00001001 // 00001001
// 7654³210 // 7654³210
isLeftPodInEar shouldBe true isLeftPodInEar shouldBe true
} }
create<DualApplePods>("07 19 01 0E 20 >20< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >20< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00000001 // 00000001
// 7654³210 // 7654³210
isLeftPodInEar shouldBe false isLeftPodInEar shouldBe false
@@ -68,24 +68,24 @@ class DualApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test AirPodDevice - right pod ear status`() = runBlockingTest { fun `test AirPodDevice - right pod ear status`() = runBlockingTest {
// Left Pod primary // Left Pod primary
create<DualApplePods>("07 19 01 0E 20 >29< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >29< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00101001 // 00101001
// 7654³210 // 7654³210
isRightPodInEar shouldBe true isRightPodInEar shouldBe true
} }
create<DualApplePods>("07 19 01 0E 20 >21< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >21< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00100001 // 00100001
// 7654³210 // 7654³210
isRightPodInEar shouldBe false isRightPodInEar shouldBe false
} }
// Right Pod is primary // Right Pod is primary
create<DualApplePods>("07 19 01 0E 20 >03< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >03< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00000011 // 00000011
// 765432¹0 // 765432¹0
isRightPodInEar shouldBe true isRightPodInEar shouldBe true
} }
create<DualApplePods>("07 19 01 0E 20 >01< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") { create<DualAirPods>("07 19 01 0E 20 >01< AA B5 31 00 00 E0 0C A7 8A 60 4B D3 7D F4 60 4F 2C 73 E9 A7 F4") {
// 00000001 // 00000001
// 765432¹0 // 765432¹0
isRightPodInEar shouldBe false isRightPodInEar shouldBe false
@@ -95,13 +95,13 @@ class DualApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test AirPodDevice - battery status`() = runBlockingTest { fun `test AirPodDevice - battery status`() = runBlockingTest {
// Right Pod is primary // Right Pod is primary
create<DualApplePods>("07 19 01 0E 20 0B >98< 94 52 00 05 09 73 3C 3D F9 2C 3E B3 DD 76 02 DD 4E 16 FD FB") { create<DualAirPods>("07 19 01 0E 20 0B >98< 94 52 00 05 09 73 3C 3D F9 2C 3E B3 DD 76 02 DD 4E 16 FD FB") {
// 88 10001000 // 88 10001000
batteryLeftPodPercent shouldBe 0.9f batteryLeftPodPercent shouldBe 0.9f
batteryRightPodPercent shouldBe 0.8f batteryRightPodPercent shouldBe 0.8f
} }
// Left Pod primary // Left Pod primary
create<DualApplePods>("07 19 01 0E 20 2B >89< 94 52 00 05 09 73 3C 3D F9 2C 3E B3 DD 76 02 DD 4E 16 FD FB") { create<DualAirPods>("07 19 01 0E 20 2B >89< 94 52 00 05 09 73 3C 3D F9 2C 3E B3 DD 76 02 DD 4E 16 FD FB") {
// F8 11111000 // F8 11111000
batteryLeftPodPercent shouldBe 0.9f batteryLeftPodPercent shouldBe 0.9f
batteryRightPodPercent shouldBe 0.8f batteryRightPodPercent shouldBe 0.8f
@@ -114,13 +114,13 @@ class DualApplePodsTest : BaseAirPodsTest() {
* Right pod is charging * Right pod is charging
*/ */
// This is the left // This is the left
create<DualApplePods>("07 19 01 0E 20 51 89 >94< 52 00 00 F4 89 82 6D 3E 27 7F 26 62 57 D0 E2 A6 49 E9 35") { create<DualAirPods>("07 19 01 0E 20 51 89 >94< 52 00 00 F4 89 82 6D 3E 27 7F 26 62 57 D0 E2 A6 49 E9 35") {
// 1001 0100 // 1001 0100
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
isRightPodCharging shouldBe true isRightPodCharging shouldBe true
} }
// This is the right // This is the right
create<DualApplePods>("07 19 01 0E 20 31 98 >A4< 01 00 00 31 B9 A0 C4 80 CD D1 CF B9 3A 9A 6D 48 31 08 EB") { create<DualAirPods>("07 19 01 0E 20 31 98 >A4< 01 00 00 31 B9 A0 C4 80 CD D1 CF B9 3A 9A 6D 48 31 08 EB") {
// 1010 0100 // 1010 0100
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
isRightPodCharging shouldBe true isRightPodCharging shouldBe true
@@ -130,26 +130,26 @@ class DualApplePodsTest : BaseAirPodsTest() {
* Left pod is charging * Left pod is charging
*/ */
// This is the left // This is the left
create<DualApplePods>("07 19 01 0E 20 71 98 >94< 52 00 05 A5 37 31 B2 BD 42 68 0C 64 FD 00 99 4A E5 3E F4") { create<DualAirPods>("07 19 01 0E 20 71 98 >94< 52 00 05 A5 37 31 B2 BD 42 68 0C 64 FD 00 99 4A E5 3E F4") {
// 1001 0100 // 1001 0100
isLeftPodCharging shouldBe true isLeftPodCharging shouldBe true
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
} }
// This is the right // This is the right
create<DualApplePods>("07 19 01 0E 20 11 89 >A4< 04 00 04 BA 79 1B C0 65 69 C6 9F 19 6E 37 7D 6D 86 8D D9") { create<DualAirPods>("07 19 01 0E 20 11 89 >A4< 04 00 04 BA 79 1B C0 65 69 C6 9F 19 6E 37 7D 6D 86 8D D9") {
// 1010 0100 // 1010 0100
isLeftPodCharging shouldBe true isLeftPodCharging shouldBe true
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
} }
// Both charging // Both charging
create<DualApplePods>("07 19 01 0E 20 55 88 >B4< 59 00 05 4B FC DF 68 28 A5 45 52 65 9C FE 51 86 3A B5 DB") { create<DualAirPods>("07 19 01 0E 20 55 88 >B4< 59 00 05 4B FC DF 68 28 A5 45 52 65 9C FE 51 86 3A B5 DB") {
// 1011 0100 // 1011 0100
isLeftPodCharging shouldBe true isLeftPodCharging shouldBe true
isRightPodCharging shouldBe true isRightPodCharging shouldBe true
} }
// Both not charging // Both not charging
create<DualApplePods>("07 19 01 0E 20 00 F8 >8F< 03 00 05 4C 0F A0 C4 05 24 DD EB AF 92 99 FD 54 B1 06 48") { create<DualAirPods>("07 19 01 0E 20 00 F8 >8F< 03 00 05 4C 0F A0 C4 05 24 DD EB AF 92 99 FD 54 B1 06 48") {
// 1000 1111 // 1000 1111
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
@@ -158,11 +158,11 @@ class DualApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test AirPodDevice - case charging`() = runBlockingTest { fun `test AirPodDevice - case charging`() = runBlockingTest {
create<DualApplePods>("07 19 01 0E 20 75 99 >B4< 31 00 05 77 C8 BA 0C 4E 1F BE AD 70 C5 40 71 D2 E9 17 A2") { create<DualAirPods>("07 19 01 0E 20 75 99 >B4< 31 00 05 77 C8 BA 0C 4E 1F BE AD 70 C5 40 71 D2 E9 17 A2") {
// 0011 0011 // 0011 0011
isCaseCharging shouldBe false isCaseCharging shouldBe false
} }
create<DualApplePods>("07 19 01 0E 20 75 A9 >F4< 51 00 05 A0 37 92 35 49 79 CC DC 27 94 8E FB 72 12 94 52") { create<DualAirPods>("07 19 01 0E 20 75 A9 >F4< 51 00 05 A0 37 92 35 49 79 CC DC 27 94 8E FB 72 12 94 52") {
// 0101 0011 // 0101 0011
isCaseCharging shouldBe true isCaseCharging shouldBe true
} }
@@ -171,75 +171,75 @@ class DualApplePodsTest : BaseAirPodsTest() {
@Test @Test
fun `test AirPodDevice - case lid test`() = runBlockingTest { fun `test AirPodDevice - case lid test`() = runBlockingTest {
// Lid open // Lid open
create<DualApplePods>("07 19 01 0E 20 55 AA B4 >31< 00 00 A1 D0 BD 82 D3 52 86 CA FC 11 62 DC 42 C6 92 8E") { create<DualAirPods>("07 19 01 0E 20 55 AA B4 >31< 00 00 A1 D0 BD 82 D3 52 86 CA FC 11 62 DC 42 C6 92 8E") {
// 31 0011 0001 // 31 0011 0001
caseLidState shouldBe DualApplePods.LidState.OPEN caseLidState shouldBe DualAirPods.LidState.OPEN
} }
// Lid open, left pod in case // Lid open, left pod in case
create<DualApplePods>("07 19 01 0E 20 51 9A 93 >31< 00 00 95 D0 A5 D7 E3 F4 F1 38 38 99 61 3B 57 95 37 B7") { create<DualAirPods>("07 19 01 0E 20 51 9A 93 >31< 00 00 95 D0 A5 D7 E3 F4 F1 38 38 99 61 3B 57 95 37 B7") {
// 31 0011 0001 // 31 0011 0001
caseLidState shouldBe DualApplePods.LidState.OPEN caseLidState shouldBe DualAirPods.LidState.OPEN
} }
// Lid open, left pod in case // Lid open, left pod in case
create<DualApplePods>("07 19 01 0E 20 71 A9 92 31 00 00 DB 48 7F 32 8C CE 80 6F D9 27 98 D6 76 45 9D 62") { create<DualAirPods>("07 19 01 0E 20 71 A9 92 31 00 00 DB 48 7F 32 8C CE 80 6F D9 27 98 D6 76 45 9D 62") {
// 31 0011 0001 // 31 0011 0001
caseLidState shouldBe DualApplePods.LidState.OPEN caseLidState shouldBe DualAirPods.LidState.OPEN
} }
// Lid just closed // Lid just closed
create<DualApplePods>("07 19 01 0E 20 55 AA B4 >39< 00 00 08 A6 DB 99 E0 5E 14 85 E5 C2 0B 68 D7 FF C3 A1") { create<DualAirPods>("07 19 01 0E 20 55 AA B4 >39< 00 00 08 A6 DB 99 E0 5E 14 85 E5 C2 0B 68 D7 FF C3 A1") {
// 39 0011 1001 // 39 0011 1001
caseLidState shouldBe DualApplePods.LidState.CLOSED caseLidState shouldBe DualAirPods.LidState.CLOSED
} }
// Lid closed // Lid closed
create<DualApplePods>("07 19 01 0E 20 55 AA B4 38 00 00 F3 F7 08 3B 98 09 C0 DD E4 BD BD 84 55 56 8B 81") { create<DualAirPods>("07 19 01 0E 20 55 AA B4 38 00 00 F3 F7 08 3B 98 09 C0 DD E4 BD BD 84 55 56 8B 81") {
// 38 0011 1000 // 38 0011 1000
caseLidState shouldBe DualApplePods.LidState.CLOSED caseLidState shouldBe DualAirPods.LidState.CLOSED
} }
// Lid closed, right pod in case // Lid closed, right pod in case
create<DualApplePods>("07 19 01 0E 20 51 9A 93 >38< 00 00 3A D8 85 76 B0 91 48 31 DA FF 6C 4A 2B C2 67 F4") { create<DualAirPods>("07 19 01 0E 20 51 9A 93 >38< 00 00 3A D8 85 76 B0 91 48 31 DA FF 6C 4A 2B C2 67 F4") {
// 38 0011 1000 // 38 0011 1000
caseLidState shouldBe DualApplePods.LidState.CLOSED caseLidState shouldBe DualAirPods.LidState.CLOSED
} }
// Lid closed, left pod in case // Lid closed, left pod in case
create<DualApplePods>("07 19 01 0E 20 71 A9 92 38 00 00 44 91 C4 8B 85 98 DD 55 4E 6A CA BC B5 CA 8D 37") { create<DualAirPods>("07 19 01 0E 20 71 A9 92 38 00 00 44 91 C4 8B 85 98 DD 55 4E 6A CA BC B5 CA 8D 37") {
// 38 0011 1000 // 38 0011 1000
caseLidState shouldBe DualApplePods.LidState.CLOSED caseLidState shouldBe DualAirPods.LidState.CLOSED
} }
} }
@Test @Test
fun `test AirPodDevice - connection state`() = runBlockingTest { fun `test AirPodDevice - connection state`() = runBlockingTest {
// Disconnected // Disconnected
create<DualApplePods>("07 19 01 0E 20 2B AA 8F 01 00 >00< 62 D4 BB F1 A7 F8 64 98 D2 C8 BD 7B 3A EF 2E 15") { create<DualAirPods>("07 19 01 0E 20 2B AA 8F 01 00 >00< 62 D4 BB F1 A7 F8 64 98 D2 C8 BD 7B 3A EF 2E 15") {
// 31 0011 0001 // 31 0011 0001
connectionState shouldBe DualApplePods.ConnectionState.DISCONNECTED state shouldBe DualAirPods.ConnectionState.DISCONNECTED
} }
// Connected idle // Connected idle
create<DualApplePods>("07 19 01 0E 20 2B AA 8F 01 00 >04< 1D 69 69 9C C2 51 F3 1F BF 6E 45 DA 90 4A A3 E3") { create<DualAirPods>("07 19 01 0E 20 2B AA 8F 01 00 >04< 1D 69 69 9C C2 51 F3 1F BF 6E 45 DA 90 4A A3 E3") {
// 39 0011 1001 // 39 0011 1001
connectionState shouldBe DualApplePods.ConnectionState.IDLE state shouldBe DualAirPods.ConnectionState.IDLE
} }
// Connected and playing music // Connected and playing music
create<DualApplePods>("07 19 01 0E 20 2B A9 8F 01 00 >05< 14 F7 CB 49 9F D3 B3 22 77 D2 22 F1 74 8C AC A6") { create<DualAirPods>("07 19 01 0E 20 2B A9 8F 01 00 >05< 14 F7 CB 49 9F D3 B3 22 77 D2 22 F1 74 8C AC A6") {
// 38 0011 1000 // 38 0011 1000
connectionState shouldBe DualApplePods.ConnectionState.MUSIC state shouldBe DualAirPods.ConnectionState.MUSIC
} }
// Connected and call active // Connected and call active
create<DualApplePods>("07 19 01 0E 20 2B 99 8F 01 00 >06< 0F 4B 43 25 E0 4A 73 63 14 22 C2 3C 89 13 BD 97") { create<DualAirPods>("07 19 01 0E 20 2B 99 8F 01 00 >06< 0F 4B 43 25 E0 4A 73 63 14 22 C2 3C 89 13 BD 97") {
// 38 0011 1000 // 38 0011 1000
connectionState shouldBe DualApplePods.ConnectionState.CALL state shouldBe DualAirPods.ConnectionState.CALL
} }
// Connected and call active // Connected and call active
create<DualApplePods>("07 19 01 0E 20 2B 99 8F 01 00 >07< E7 DF 76 44 85 B5 30 F4 95 14 02 DC A1 A4 8A 09") { create<DualAirPods>("07 19 01 0E 20 2B 99 8F 01 00 >07< E7 DF 76 44 85 B5 30 F4 95 14 02 DC A1 A4 8A 09") {
// 38 0011 1000 // 38 0011 1000
connectionState shouldBe DualApplePods.ConnectionState.RINGING state shouldBe DualAirPods.ConnectionState.RINGING
} }
// Switching? // Switching?
create<DualApplePods>("07 19 01 0E 20 2B 99 8F 01 00 >09< 10 30 EE F3 41 B5 D8 9F A3 B0 B4 17 9F 85 97 5F") { create<DualAirPods>("07 19 01 0E 20 2B 99 8F 01 00 >09< 10 30 EE F3 41 B5 D8 9F A3 B0 B4 17 9F 85 97 5F") {
// 38 0011 1000 // 38 0011 1000
connectionState shouldBe DualApplePods.ConnectionState.HANGING_UP state shouldBe DualAirPods.ConnectionState.HANGING_UP
} }
} }
@@ -1,7 +1,8 @@
package eu.darken.capod.pods.core.apple.airpods package eu.darken.capod.pods.core.apple.airpods
import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.BaseAirPodsTest
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.HasAppleColor
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.runBlockingTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -33,11 +34,11 @@ class AirPodsGen1Test : BaseAirPodsTest() {
isRightPodInEar shouldBe false isRightPodInEar shouldBe false
batteryCasePercent shouldBe 0.6f batteryCasePercent shouldBe 0.6f
caseLidState shouldBe DualApplePods.LidState.OPEN caseLidState shouldBe DualAirPods.LidState.OPEN
connectionState shouldBe DualApplePods.ConnectionState.DISCONNECTED state shouldBe DualAirPods.ConnectionState.DISCONNECTED
deviceColor shouldBe DualApplePods.DeviceColor.WHITE podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name
} }
} }
} }
@@ -1,7 +1,8 @@
package eu.darken.capod.pods.core.apple.airpods package eu.darken.capod.pods.core.apple.airpods
import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.BaseAirPodsTest
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.HasAppleColor
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.runBlockingTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -32,11 +33,11 @@ class AirPodsGen2Test : BaseAirPodsTest() {
isRightPodInEar shouldBe true isRightPodInEar shouldBe true
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
caseLidState shouldBe DualApplePods.LidState.NOT_IN_CASE caseLidState shouldBe DualAirPods.LidState.NOT_IN_CASE
connectionState shouldBe DualApplePods.ConnectionState.MUSIC state shouldBe DualAirPods.ConnectionState.MUSIC
deviceColor shouldBe DualApplePods.DeviceColor.WHITE podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name
} }
} }
} }
@@ -1,7 +1,8 @@
package eu.darken.capod.pods.core.apple.airpods package eu.darken.capod.pods.core.apple.airpods
import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.BaseAirPodsTest
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.DualAirPods
import eu.darken.capod.pods.core.apple.HasAppleColor
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.runBlockingTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -32,11 +33,11 @@ class AirPodsGen3Test : BaseAirPodsTest() {
isRightPodInEar shouldBe false isRightPodInEar shouldBe false
batteryCasePercent shouldBe 0.9f batteryCasePercent shouldBe 0.9f
caseLidState shouldBe DualApplePods.LidState.OPEN caseLidState shouldBe DualAirPods.LidState.OPEN
connectionState shouldBe DualApplePods.ConnectionState.IDLE state shouldBe DualAirPods.ConnectionState.IDLE
deviceColor shouldBe DualApplePods.DeviceColor.WHITE podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name
} }
} }
@@ -54,11 +55,11 @@ class AirPodsGen3Test : BaseAirPodsTest() {
isRightPodInEar shouldBe true isRightPodInEar shouldBe true
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
caseLidState shouldBe DualApplePods.LidState.NOT_IN_CASE caseLidState shouldBe DualAirPods.LidState.NOT_IN_CASE
connectionState shouldBe DualApplePods.ConnectionState.UNKNOWN state shouldBe DualAirPods.ConnectionState.UNKNOWN
deviceColor shouldBe DualApplePods.DeviceColor.WHITE podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name
} }
} }
} }
@@ -1,7 +1,7 @@
package eu.darken.capod.pods.core.apple.airpods package eu.darken.capod.pods.core.apple.airpods
import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.BaseAirPodsTest
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.HasAppleColor
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.runBlockingTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -33,7 +33,7 @@ class AirPodsProTest : BaseAirPodsTest() {
isLeftPodCharging shouldBe true isLeftPodCharging shouldBe true
batteryCasePercent shouldBe 0.5f batteryCasePercent shouldBe 0.5f
deviceColor shouldBe DualApplePods.DeviceColor.WHITE podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name
} }
} }
@@ -50,8 +50,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
} }
@@ -66,8 +64,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e202b668f01000500000000000000000000000000000000") { create<AirPodsPro>("0719010e202b668f01000500000000000000000000000000000000") {
@@ -78,8 +74,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e202b668f01000400000000000000000000000000000000") { create<AirPodsPro>("0719010e202b668f01000400000000000000000000000000000000") {
@@ -90,8 +84,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e200b668f01000500000000000000000000000000000000") { create<AirPodsPro>("0719010e200b668f01000500000000000000000000000000000000") {
@@ -102,8 +94,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e2003668f01000500000000000000000000000000000000") { create<AirPodsPro>("0719010e2003668f01000500000000000000000000000000000000") {
@@ -114,8 +104,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e2001668f01000500000000000000000000000000000000") { create<AirPodsPro>("0719010e2001668f01000500000000000000000000000000000000") {
@@ -126,8 +114,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e2009668f01000500000000000000000000000000000000") { create<AirPodsPro>("0719010e2009668f01000500000000000000000000000000000000") {
@@ -138,8 +124,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe null batteryCasePercent shouldBe null
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e2053669653000500000000000000000000000000000000") { create<AirPodsPro>("0719010e2053669653000500000000000000000000000000000000") {
@@ -150,8 +134,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe true isRightPodCharging shouldBe true
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe 0.6f batteryCasePercent shouldBe 0.6f
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e203366a602000500000000000000000000000000000000") { create<AirPodsPro>("0719010e203366a602000500000000000000000000000000000000") {
@@ -162,8 +144,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe true isRightPodCharging shouldBe true
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe 0.6f batteryCasePercent shouldBe 0.6f
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
create<AirPodsPro>("0719010e202b768f02000500000000000000000000000000000000") { create<AirPodsPro>("0719010e202b768f02000500000000000000000000000000000000") {
@@ -174,8 +154,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe false isRightPodCharging shouldBe false
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe 0.6f batteryCasePercent shouldBe 0.6f
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
} }
@@ -190,8 +168,6 @@ class AirPodsProTest : BaseAirPodsTest() {
isRightPodCharging shouldBe true isRightPodCharging shouldBe true
isLeftPodCharging shouldBe false isLeftPodCharging shouldBe false
batteryCasePercent shouldBe 0.6f batteryCasePercent shouldBe 0.6f
deviceColor shouldBe DualApplePods.DeviceColor.WHITE
} }
} }
} }
@@ -1,7 +1,7 @@
package eu.darken.capod.pods.core.apple.beats package eu.darken.capod.pods.core.apple.beats
import eu.darken.capod.pods.core.apple.BaseAirPodsTest import eu.darken.capod.pods.core.apple.BaseAirPodsTest
import eu.darken.capod.pods.core.apple.DualApplePods import eu.darken.capod.pods.core.apple.HasAppleColor
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.runBlockingTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@@ -33,7 +33,7 @@ class PowerBeatsProTest : BaseAirPodsTest() {
isLeftPodCharging shouldBe true isLeftPodCharging shouldBe true
batteryCasePercent shouldBe 0.5f batteryCasePercent shouldBe 0.5f
deviceColor shouldBe DualApplePods.DeviceColor.WHITE podStyle.identifier shouldBe HasAppleColor.DeviceColor.WHITE.name
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More