Restored bluetooth support when Telecom Framework is not active
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.tutpro.baresip
|
package com.tutpro.baresip
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.Manifest.permission.RECORD_AUDIO
|
import android.Manifest.permission.RECORD_AUDIO
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
@@ -7,6 +8,9 @@ import android.app.NotificationChannel
|
|||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
|
import android.bluetooth.BluetoothAdapter
|
||||||
|
import android.bluetooth.BluetoothHeadset
|
||||||
|
import android.bluetooth.BluetoothManager
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -59,6 +63,7 @@ import androidx.appcompat.app.AppCompatDelegate
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationCompat.MessagingStyle
|
import androidx.core.app.NotificationCompat.MessagingStyle
|
||||||
import androidx.core.app.Person
|
import androidx.core.app.Person
|
||||||
@@ -93,10 +98,12 @@ class BaresipService: Service() {
|
|||||||
private lateinit var pm: PowerManager
|
private lateinit var pm: PowerManager
|
||||||
private lateinit var wm: WifiManager
|
private lateinit var wm: WifiManager
|
||||||
private lateinit var tm: TelecomManager
|
private lateinit var tm: TelecomManager
|
||||||
|
private lateinit var btm: BluetoothManager
|
||||||
private lateinit var vibrator: Vibrator
|
private lateinit var vibrator: Vibrator
|
||||||
private lateinit var partialWakeLock: PowerManager.WakeLock
|
private lateinit var partialWakeLock: PowerManager.WakeLock
|
||||||
private lateinit var proximityWakeLock: PowerManager.WakeLock
|
private lateinit var proximityWakeLock: PowerManager.WakeLock
|
||||||
private lateinit var wifiLock: WifiManager.WifiLock
|
private lateinit var wifiLock: WifiManager.WifiLock
|
||||||
|
private lateinit var bluetoothReceiver: BroadcastReceiver
|
||||||
private lateinit var hotSpotReceiver: BroadcastReceiver
|
private lateinit var hotSpotReceiver: BroadcastReceiver
|
||||||
private lateinit var androidContactsObserver: ContentObserver
|
private lateinit var androidContactsObserver: ContentObserver
|
||||||
private lateinit var networkCallback: ConnectivityManager.NetworkCallback
|
private lateinit var networkCallback: ConnectivityManager.NetworkCallback
|
||||||
@@ -113,6 +120,7 @@ class BaresipService: Service() {
|
|||||||
private var mediaPlayer: MediaPlayer? = null
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
private var androidContactsObserverRegistered = false
|
private var androidContactsObserverRegistered = false
|
||||||
private var hotSpotReceiverRegistered = false
|
private var hotSpotReceiverRegistered = false
|
||||||
|
private var bluetoothReceiverRegistered = false
|
||||||
private var isNotificationInCall = false
|
private var isNotificationInCall = false
|
||||||
private var isServiceClean = false
|
private var isServiceClean = false
|
||||||
private var cleanupRunnable: Runnable? = null
|
private var cleanupRunnable: Runnable? = null
|
||||||
@@ -281,7 +289,64 @@ class BaresipService: Service() {
|
|||||||
hotSpotReceiverRegistered = true
|
hotSpotReceiverRegistered = true
|
||||||
|
|
||||||
tm = getSystemService(TELECOM_SERVICE) as TelecomManager
|
tm = getSystemService(TELECOM_SERVICE) as TelecomManager
|
||||||
registerPhoneAccount()
|
|
||||||
|
btm = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager
|
||||||
|
btAdapter = btm.adapter
|
||||||
|
|
||||||
|
bluetoothReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(ctx: Context, intent: Intent) {
|
||||||
|
when (intent.action) {
|
||||||
|
BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED -> {
|
||||||
|
val state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
|
||||||
|
BluetoothHeadset.STATE_DISCONNECTED)
|
||||||
|
when (state) {
|
||||||
|
BluetoothHeadset.STATE_CONNECTED -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset is connected")
|
||||||
|
if (audioFocusRequest != null)
|
||||||
|
startBluetoothSco(applicationContext, 1000L, 3)
|
||||||
|
}
|
||||||
|
BluetoothHeadset.STATE_DISCONNECTED -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset is disconnected")
|
||||||
|
if (audioFocusRequest != null)
|
||||||
|
stopBluetoothSco(applicationContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED -> {
|
||||||
|
val state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
|
||||||
|
BluetoothHeadset.STATE_AUDIO_DISCONNECTED)
|
||||||
|
when (state) {
|
||||||
|
BluetoothHeadset.STATE_AUDIO_CONNECTED -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset audio is connected")
|
||||||
|
}
|
||||||
|
BluetoothHeadset.STATE_AUDIO_DISCONNECTED -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset audio is disconnected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED -> {
|
||||||
|
val state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
|
||||||
|
AudioManager.SCO_AUDIO_STATE_DISCONNECTED)
|
||||||
|
when (state) {
|
||||||
|
AudioManager.SCO_AUDIO_STATE_CONNECTING -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset SCO is connecting")
|
||||||
|
}
|
||||||
|
AudioManager.SCO_AUDIO_STATE_CONNECTED -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset SCO is connected")
|
||||||
|
}
|
||||||
|
AudioManager.SCO_AUDIO_STATE_DISCONNECTED -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset SCO is disconnected")
|
||||||
|
resetCallVolume()
|
||||||
|
}
|
||||||
|
AudioManager.SCO_AUDIO_STATE_ERROR -> {
|
||||||
|
Log.d(TAG, "Bluetooth headset SCO state ERROR")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proximityWakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
|
proximityWakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
|
||||||
"com.tutpro.baresip:proximity_wakelock")
|
"com.tutpro.baresip:proximity_wakelock")
|
||||||
@@ -374,9 +439,10 @@ class BaresipService: Service() {
|
|||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Asset '$a' already copied")
|
Log.i(TAG, "Asset '$a' already copied")
|
||||||
}
|
}
|
||||||
if (a == "config")
|
if (a == "config") {
|
||||||
Config.initialize(applicationContext)
|
Config.initialize(applicationContext)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (contactsMode != "android")
|
if (contactsMode != "android")
|
||||||
Contact.restoreBaresipContacts()
|
Contact.restoreBaresipContacts()
|
||||||
@@ -427,6 +493,19 @@ class BaresipService: Service() {
|
|||||||
activeNetwork = cm.activeNetwork
|
activeNetwork = cm.activeNetwork
|
||||||
Log.i(TAG, "Active network: $activeNetwork")
|
Log.i(TAG, "Active network: $activeNetwork")
|
||||||
|
|
||||||
|
if (telecom)
|
||||||
|
registerPhoneAccount()
|
||||||
|
else
|
||||||
|
if (btAdapter != null) {
|
||||||
|
Log.i(TAG, "Registering bluetooth receiver")
|
||||||
|
val filter = IntentFilter()
|
||||||
|
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)
|
||||||
|
filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)
|
||||||
|
filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)
|
||||||
|
this.registerReceiver(bluetoothReceiver, filter)
|
||||||
|
bluetoothReceiverRegistered = true
|
||||||
|
}
|
||||||
|
|
||||||
Log.i(TAG, "AEC/AGC/NS available = $aecAvailable/$agcAvailable/$nsAvailable")
|
Log.i(TAG, "AEC/AGC/NS available = $aecAvailable/$agcAvailable/$nsAvailable")
|
||||||
|
|
||||||
val userAgent = Config.variable("user_agent")
|
val userAgent = Config.variable("user_agent")
|
||||||
@@ -800,7 +879,6 @@ class BaresipService: Service() {
|
|||||||
if (call!!.status.value == "transferring")
|
if (call!!.status.value == "transferring")
|
||||||
break
|
break
|
||||||
speakerPhone = speakerPhoneAuto
|
speakerPhone = speakerPhoneAuto
|
||||||
// stopRinging()
|
|
||||||
stopMediaPlayer()
|
stopMediaPlayer()
|
||||||
val hasTelecom = ConnectionService.connections.containsKey(callp) ||
|
val hasTelecom = ConnectionService.connections.containsKey(callp) ||
|
||||||
ConnectionService.pendingOutgoingConnection != null
|
ConnectionService.pendingOutgoingConnection != null
|
||||||
@@ -2238,6 +2316,12 @@ class BaresipService: Service() {
|
|||||||
} catch (_: IllegalArgumentException) {
|
} catch (_: IllegalArgumentException) {
|
||||||
Log.e(TAG, "hotSpotReceiver was not registered with applicationContext")
|
Log.e(TAG, "hotSpotReceiver was not registered with applicationContext")
|
||||||
}
|
}
|
||||||
|
if (bluetoothReceiverRegistered) {
|
||||||
|
try {
|
||||||
|
unregisterReceiver(bluetoothReceiver)
|
||||||
|
bluetoothReceiverRegistered = false
|
||||||
|
} catch (_: IllegalArgumentException) {}
|
||||||
|
}
|
||||||
val callps = ConnectionService.connections.keys.toList()
|
val callps = ConnectionService.connections.keys.toList()
|
||||||
for (callp in callps)
|
for (callp in callps)
|
||||||
ConnectionService.onCallClosed(callp)
|
ConnectionService.onCallClosed(callp)
|
||||||
@@ -2289,6 +2373,7 @@ class BaresipService: Service() {
|
|||||||
var isConfigInitialized = false
|
var isConfigInitialized = false
|
||||||
var libraryLoaded = false
|
var libraryLoaded = false
|
||||||
var callVolume = 0
|
var callVolume = 0
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var speakerPhone = false
|
var speakerPhone = false
|
||||||
var speakerPhoneAuto = false
|
var speakerPhoneAuto = false
|
||||||
@@ -2329,6 +2414,7 @@ class BaresipService: Service() {
|
|||||||
var contactsMode by mutableStateOf("baresip")
|
var contactsMode by mutableStateOf("baresip")
|
||||||
var addressFamily = ""
|
var addressFamily = ""
|
||||||
var dnsServers = listOf<InetAddress>()
|
var dnsServers = listOf<InetAddress>()
|
||||||
|
|
||||||
// <aor, password> of those accounts that have auth username without auth password
|
// <aor, password> of those accounts that have auth username without auth password
|
||||||
val aorPasswords = mutableMapOf<String, String>()
|
val aorPasswords = mutableMapOf<String, String>()
|
||||||
var aecAvailable = false
|
var aecAvailable = false
|
||||||
@@ -2338,17 +2424,24 @@ class BaresipService: Service() {
|
|||||||
private var agc: AutomaticGainControl? = null
|
private var agc: AutomaticGainControl? = null
|
||||||
private var ns: NoiseSuppressor? = null
|
private var ns: NoiseSuppressor? = null
|
||||||
private var recorderSessionId = 0
|
private var recorderSessionId = 0
|
||||||
|
private var btAdapter: BluetoothAdapter? = null
|
||||||
private var audioFocusRequest: androidx.media.AudioFocusRequestCompat? = null
|
private var audioFocusRequest: androidx.media.AudioFocusRequestCompat? = null
|
||||||
|
|
||||||
var rt: Ringtone? = null
|
var rt: Ringtone? = null
|
||||||
|
|
||||||
var colorblind = false
|
var colorblind = false
|
||||||
val circleGreen = mapOf(true to R.drawable.circle_green_blind,
|
val circleGreen = mapOf(
|
||||||
false to R.drawable.circle_green)
|
true to R.drawable.circle_green_blind,
|
||||||
val circleYellow = mapOf(true to R.drawable.circle_yellow_blind,
|
false to R.drawable.circle_green
|
||||||
false to R.drawable.circle_yellow)
|
)
|
||||||
val circleRed = mapOf(true to R.drawable.circle_red_blind,
|
val circleYellow = mapOf(
|
||||||
false to R.drawable.circle_red)
|
true to R.drawable.circle_yellow_blind,
|
||||||
|
false to R.drawable.circle_yellow
|
||||||
|
)
|
||||||
|
val circleRed = mapOf(
|
||||||
|
true to R.drawable.circle_red_blind,
|
||||||
|
false to R.drawable.circle_red
|
||||||
|
)
|
||||||
|
|
||||||
internal const val KEY_TEXT_REPLY = "key_text_reply_baresip"
|
internal const val KEY_TEXT_REPLY = "key_text_reply_baresip"
|
||||||
private const val PHONE_ACCOUNT_ID = "baresip_phone_account"
|
private const val PHONE_ACCOUNT_ID = "baresip_phone_account"
|
||||||
@@ -2363,9 +2456,9 @@ class BaresipService: Service() {
|
|||||||
if (serviceEvents.size == 1) {
|
if (serviceEvents.size == 1) {
|
||||||
Log.d(TAG, "Posted service event ${event.event} at ${event.timeStamp}")
|
Log.d(TAG, "Posted service event ${event.event} at ${event.timeStamp}")
|
||||||
serviceEvent.postValue(Event(event.timeStamp))
|
serviceEvent.postValue(Event(event.timeStamp))
|
||||||
} else {
|
|
||||||
Log.d(TAG, "Added service event ${event.event}")
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Log.d(TAG, "Added service event ${event.event}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestAudioFocus(ctx: Context): Boolean {
|
fun requestAudioFocus(ctx: Context): Boolean {
|
||||||
@@ -2390,7 +2483,10 @@ class BaresipService: Service() {
|
|||||||
) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
|
) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
|
||||||
) {
|
) {
|
||||||
Log.d(TAG, "requestAudioFocus granted")
|
Log.d(TAG, "requestAudioFocus granted")
|
||||||
} else {
|
if (!telecom && isBluetoothHeadsetConnected(ctx))
|
||||||
|
startBluetoothSco(ctx, 250L, 3)
|
||||||
|
}
|
||||||
|
else {
|
||||||
Log.w(TAG, "requestAudioFocus denied")
|
Log.w(TAG, "requestAudioFocus denied")
|
||||||
audioFocusRequest = null
|
audioFocusRequest = null
|
||||||
}
|
}
|
||||||
@@ -2408,11 +2504,75 @@ class BaresipService: Service() {
|
|||||||
AudioManager.AUDIOFOCUS_REQUEST_GRANTED
|
AudioManager.AUDIOFOCUS_REQUEST_GRANTED
|
||||||
) {
|
) {
|
||||||
audioFocusRequest = null
|
audioFocusRequest = null
|
||||||
} else {
|
if (!telecom && isBluetoothHeadsetConnected(ctx))
|
||||||
Log.e(TAG, "Failed to abandon audio focus")
|
stopBluetoothSco(ctx)
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Log.e(TAG, "Failed to abandon audio focus")
|
||||||
}
|
}
|
||||||
am.mode = MODE_NORMAL
|
am.mode = MODE_NORMAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isBluetoothHeadsetConnected(ctx: Context): Boolean {
|
||||||
|
if (VERSION.SDK_INT >= 31 &&
|
||||||
|
ActivityCompat.checkSelfPermission(
|
||||||
|
ctx,
|
||||||
|
Manifest.permission.BLUETOOTH_CONNECT
|
||||||
|
) == PackageManager.PERMISSION_DENIED
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
return btAdapter != null && btAdapter!!.isEnabled &&
|
||||||
|
btAdapter!!.getProfileConnectionState(BluetoothHeadset.HEADSET) ==
|
||||||
|
BluetoothAdapter.STATE_CONNECTED
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isBluetoothScoOn(am: AudioManager): Boolean {
|
||||||
|
return if (VERSION.SDK_INT < 31)
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
am.isBluetoothScoOn
|
||||||
|
else
|
||||||
|
if (am.communicationDevice != null)
|
||||||
|
am.communicationDevice!!.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO
|
||||||
|
else
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startBluetoothSco(ctx: Context, delay: Long, count: Int) {
|
||||||
|
val am = ctx.getSystemService(AUDIO_SERVICE) as AudioManager
|
||||||
|
if (isBluetoothScoOn(am)) {
|
||||||
|
Log.d(TAG, "Bluetooth SCO is already on")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Log.d(TAG, "Starting Bluetooth SCO at count $count")
|
||||||
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
|
if (VERSION.SDK_INT < 31) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
am.startBluetoothSco()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Utils.setCommunicationDevice(am, AudioDeviceInfo.TYPE_BLUETOOTH_SCO)
|
||||||
|
if (!isBluetoothScoOn(am) && count > 1)
|
||||||
|
startBluetoothSco(ctx, delay, count - 1)
|
||||||
|
else
|
||||||
|
am.isBluetoothScoOn = true
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopBluetoothSco(ctx: Context) {
|
||||||
|
Log.d(TAG, "Stopping Bluetooth SCO")
|
||||||
|
val am = ctx.getSystemService(AUDIO_SERVICE) as AudioManager
|
||||||
|
if (!isBluetoothScoOn(am)) {
|
||||||
|
Log.d(TAG, "Bluetooth SCO is already off")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
|
if (VERSION.SDK_INT < 31)
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
am.stopBluetoothSco()
|
||||||
|
else
|
||||||
|
am.clearCommunicationDevice()
|
||||||
|
am.isBluetoothScoOn = false
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,13 @@ class ConnectionService : ConnectionService() {
|
|||||||
connections[callp]?.let {
|
connections[callp]?.let {
|
||||||
Log.d(TAG, "Setting audio route for $callp to speaker=$speaker")
|
Log.d(TAG, "Setting audio route for $callp to speaker=$speaker")
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
it.setAudioRoute(if (speaker) CallAudioState.ROUTE_SPEAKER else CallAudioState.ROUTE_EARPIECE)
|
val currentRoute = it.callAudioState?.route ?: CallAudioState.ROUTE_EARPIECE
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
if (speaker) {
|
||||||
|
it.setAudioRoute(CallAudioState.ROUTE_SPEAKER)
|
||||||
|
} else if (currentRoute == CallAudioState.ROUTE_SPEAKER) {
|
||||||
|
it.setAudioRoute(CallAudioState.ROUTE_EARPIECE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -957,20 +957,22 @@ object Utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleSpeakerPhone(executor: Executor, am: AudioManager) {
|
@RequiresApi(Build.VERSION_CODES.S)
|
||||||
val isSpeakerOn = if (Build.VERSION.SDK_INT >= 31) {
|
fun setCommunicationDevice(am: AudioManager, type: Int) {
|
||||||
am.communicationDevice?.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER
|
val current = am.communicationDevice!!.type
|
||||||
} else {
|
Log.d(TAG, "Current com dev/mode $current/${am.mode}")
|
||||||
@Suppress("DEPRECATION")
|
for (device in am.availableCommunicationDevices)
|
||||||
am.isSpeakerphoneOn
|
if (device.type == type) {
|
||||||
|
am.setCommunicationDevice(device)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
setSpeakerPhone(executor, am, !isSpeakerOn)
|
Log.d(TAG, "New com dev/mode ${am.communicationDevice!!.type}/${am.mode}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearCommunicationDevice(am: AudioManager) {
|
fun clearCommunicationDevice(am: AudioManager) {
|
||||||
if (Build.VERSION.SDK_INT >= 31) {
|
if (Build.VERSION.SDK_INT >= 31)
|
||||||
am.clearCommunicationDevice()
|
am.clearCommunicationDevice()
|
||||||
} else {
|
else {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
am.isSpeakerphoneOn = false
|
am.isSpeakerphoneOn = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -436,8 +436,8 @@
|
|||||||
<string name="proximity_sensing_help">Jos merkitty, läheisyyden tunnistus on aktiivinen
|
<string name="proximity_sensing_help">Jos merkitty, läheisyyden tunnistus on aktiivinen
|
||||||
puhelun aikana.</string>
|
puhelun aikana.</string>
|
||||||
<string name="telecom">Telecom-kehys</string>
|
<string name="telecom">Telecom-kehys</string>
|
||||||
<string name="telecom_help">Käytä Android Telecom -kehystä puheluihin. Poista valinta, jos puhelun toinen osapuoli ei kuule ääntäsi.
|
<string name="telecom_help">Käytä Android Telecom-kehystä puheluihin. Poista valinta, jos
|
||||||
Bluetooth on tuettu vain, kun Telecom-kehys on käytössä.</string>
|
puhelun toinen osapuoli ei kuule ääntäsi.</string>
|
||||||
<string name="video_size">Videon kehyskoko</string>
|
<string name="video_size">Videon kehyskoko</string>
|
||||||
<string name="video_size_help">Lähetettävän videon kehyskoko (leveys x korkeus)</string>
|
<string name="video_size_help">Lähetettävän videon kehyskoko (leveys x korkeus)</string>
|
||||||
<string name="video_fps">Videokehysten lähetystaajuus</string>
|
<string name="video_fps">Videokehysten lähetystaajuus</string>
|
||||||
|
|||||||
@@ -410,7 +410,7 @@
|
|||||||
<string name="proximity_sensing_help">If checked, proximity sensing is active during calls.</string>
|
<string name="proximity_sensing_help">If checked, proximity sensing is active during calls.</string>
|
||||||
<string name="telecom">Telecom Framework</string>
|
<string name="telecom">Telecom Framework</string>
|
||||||
<string name="telecom_help">Use Android Telecom framework for calls. Uncheck this if peer does
|
<string name="telecom_help">Use Android Telecom framework for calls. Uncheck this if peer does
|
||||||
not hear your audio. Bluetooth is supported only when Telecom Framework is in use.</string>
|
not hear your audio.</string>
|
||||||
<string name="video_size">Video Frame Size</string>
|
<string name="video_size">Video Frame Size</string>
|
||||||
<string name="video_size_help">Size of transmitted video frames (width x height)</string>
|
<string name="video_size_help">Size of transmitted video frames (width x height)</string>
|
||||||
<string name="video_fps">Video Frames Per Second</string>
|
<string name="video_fps">Video Frames Per Second</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user