Compare commits
10 Commits
b29ab2acd3
...
2372b7fe05
| Author | SHA1 | Date | |
|---|---|---|---|
| 2372b7fe05 | |||
| e572b2df53 | |||
| ed39535e05 | |||
| 77bfe351f2 | |||
| 11619a9130 | |||
| 196205200c | |||
| 78aab58051 | |||
| 06f6705450 | |||
| 925f0340d0 | |||
| 79ea123143 |
BIN
.agentbridge/conversation.db
Normal file
BIN
.agentbridge/conversation.db
Normal file
Binary file not shown.
BIN
.agentbridge/conversation.db-shm
Normal file
BIN
.agentbridge/conversation.db-shm
Normal file
Binary file not shown.
BIN
.agentbridge/conversation.db-wal
Normal file
BIN
.agentbridge/conversation.db-wal
Normal file
Binary file not shown.
18
.gitignore
vendored
18
.gitignore
vendored
@ -9,10 +9,28 @@ java_*
|
|||||||
.gradle
|
.gradle
|
||||||
/local.properties
|
/local.properties
|
||||||
build
|
build
|
||||||
|
/app/build
|
||||||
/captures
|
/captures
|
||||||
|
*.apk
|
||||||
|
*.ap_
|
||||||
|
*.dex
|
||||||
|
*.class
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
/app/release
|
/app/release
|
||||||
/app/.cxx
|
/app/.cxx
|
||||||
gradle/wrapper/gradle-wrapper.jar
|
gradle/wrapper/gradle-wrapper.jar
|
||||||
/distribution/*
|
/distribution/*
|
||||||
/distribution.video/*
|
/distribution.video/*
|
||||||
|
libbaresip-android/amr
|
||||||
|
libbaresip-android/baresip
|
||||||
|
libbaresip-android/bcg729
|
||||||
|
libbaresip-android/codec2
|
||||||
|
libbaresip-android/g722
|
||||||
|
libbaresip-android/g7221
|
||||||
|
libbaresip-android/ilbc
|
||||||
|
libbaresip-android/openssl
|
||||||
|
libbaresip-android/opus
|
||||||
|
libbaresip-android/re
|
||||||
|
libbaresip-android/sndfile
|
||||||
|
libbaresip-android/vo-amrwbenc
|
||||||
|
libbaresip-android/zrtpcpp
|
||||||
|
|||||||
132
SERVER.md
Normal file
132
SERVER.md
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
# Provisioning server
|
||||||
|
|
||||||
|
Baresip Studio can provision accounts from a server-encrypted bundle using a
|
||||||
|
per-device RSA key pair generated in Android Keystore.
|
||||||
|
|
||||||
|
Endpoint contract
|
||||||
|
- Base URL: whatever you pass as `endpoint=` in the `baresip:` URI
|
||||||
|
- Path used by the app: `<endpoint>/bundle`
|
||||||
|
- Method: POST
|
||||||
|
- Request Content-Type: application/json
|
||||||
|
- Response Content-Type: application/json
|
||||||
|
|
||||||
|
Enrollment request body
|
||||||
|
{
|
||||||
|
"extension": "101",
|
||||||
|
"public_key": "<base64 DER SubjectPublicKeyInfo>"
|
||||||
|
}
|
||||||
|
|
||||||
|
Provisioning bundle response body
|
||||||
|
{
|
||||||
|
"encrypted_key": "<base64 RSA-OAEP ciphertext>",
|
||||||
|
"iv": "<base64 12-byte GCM nonce>",
|
||||||
|
"ciphertext": "<base64 AES-GCM ciphertext>",
|
||||||
|
"tag": "<base64 16-byte GCM tag>"
|
||||||
|
}
|
||||||
|
|
||||||
|
The plaintext AES-GCM payload after decryption should be a JSON object like:
|
||||||
|
{
|
||||||
|
"connect_string": "sip:101@pbx.example.com",
|
||||||
|
"transport": "tls",
|
||||||
|
"sip_verify_server": "yes",
|
||||||
|
"username": "101",
|
||||||
|
"password": "secret",
|
||||||
|
"display_name": "Extension 101",
|
||||||
|
"account_name": "Desk Phone",
|
||||||
|
"outbound1": "sip:pbx.example.com",
|
||||||
|
"outbound2": "",
|
||||||
|
"register": true,
|
||||||
|
"reg_int": 900,
|
||||||
|
"check_origin": true,
|
||||||
|
"media_enc": "",
|
||||||
|
"media_nat": "",
|
||||||
|
"stun_server": "",
|
||||||
|
"stun_user": "",
|
||||||
|
"stun_pass": "",
|
||||||
|
"rtcp_mux": false,
|
||||||
|
"rel100": false,
|
||||||
|
"dtmf_mode": 2,
|
||||||
|
"answer_mode": 0,
|
||||||
|
"auto_redirect": false,
|
||||||
|
"vm_uri": "",
|
||||||
|
"country_code": "",
|
||||||
|
"tel_provider": "",
|
||||||
|
"numeric_keypad": false,
|
||||||
|
"default_account": true,
|
||||||
|
"custom_params": "",
|
||||||
|
"client_cert": "<PEM>",
|
||||||
|
"client_key": "<PEM>",
|
||||||
|
"ca_certs": "<PEM>"
|
||||||
|
}
|
||||||
|
|
||||||
|
Python server example
|
||||||
|
- Requirements: python >= 3.10
|
||||||
|
- pip install fastapi uvicorn pydantic
|
||||||
|
|
||||||
|
from fastapi import FastAPI, HTTPException
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from cryptography.hazmat.primitives.asymmetric import padding
|
||||||
|
from cryptography.hazmat.primitives import hashes, serialization
|
||||||
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||||
|
import base64
|
||||||
|
import json
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
class EnrollRequest(BaseModel):
|
||||||
|
extension: str
|
||||||
|
public_key: str
|
||||||
|
|
||||||
|
class BundleResponse(BaseModel):
|
||||||
|
encrypted_key: str
|
||||||
|
iv: str
|
||||||
|
ciphertext: str
|
||||||
|
tag: str
|
||||||
|
|
||||||
|
SERVER_RSA_PRIVATE_KEY_PEM = """-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
...
|
||||||
|
-----END RSA PRIVATE KEY-----"""
|
||||||
|
|
||||||
|
def server_private_key():
|
||||||
|
return serialization.load_pem_private_key(
|
||||||
|
SERVER_RSA_PRIVATE_KEY_PEM.encode(), password=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@app.post("/bundle", response_model=BundleResponse)
|
||||||
|
def bundle(req: EnrollRequest):
|
||||||
|
pub = serialization.load_der_public_key(base64.b64decode(req.public_key))
|
||||||
|
aes_key = AESGCM.generate_key(bit_length=256)
|
||||||
|
aesgcm = AESGCM(aes_key)
|
||||||
|
iv = b"012345678901" # replace with os.urandom(12) in production
|
||||||
|
payload = {
|
||||||
|
"connect_string": f"sip:{req.extension}@pbx.example.com",
|
||||||
|
"transport": "tls",
|
||||||
|
"sip_verify_server": "yes",
|
||||||
|
"username": req.extension,
|
||||||
|
"password": "secret",
|
||||||
|
"client_cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
|
||||||
|
"client_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
|
||||||
|
"ca_certs": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
|
||||||
|
}
|
||||||
|
plaintext = json.dumps(payload).encode("utf-8")
|
||||||
|
encrypted = aesgcm.encrypt(iv, plaintext, None)
|
||||||
|
encrypted_key = server_private_key().encrypt(
|
||||||
|
aes_key,
|
||||||
|
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None),
|
||||||
|
)
|
||||||
|
ciphertext = encrypted[:-16]
|
||||||
|
tag = encrypted[-16:]
|
||||||
|
return BundleResponse(
|
||||||
|
encrypted_key=base64.b64encode(encrypted_key).decode(),
|
||||||
|
iv=base64.b64encode(iv).decode(),
|
||||||
|
ciphertext=base64.b64encode(ciphertext).decode(),
|
||||||
|
tag=base64.b64encode(tag).decode(),
|
||||||
|
)
|
||||||
|
|
||||||
|
Example baresip URI
|
||||||
|
baresip://provision?endpoint=https://pbx.example.com&extension=101
|
||||||
|
|
||||||
|
Security notes
|
||||||
|
- Always serve over HTTPS.
|
||||||
|
- Keep SERVER_RSA_PRIVATE_KEY_PEM secret and offline from the app.
|
||||||
|
- Treat the bundle URL as a secret; short expiry and single-use are recommended.
|
||||||
@ -13,8 +13,8 @@ configure<ApplicationExtension> {
|
|||||||
applicationId = "com.tutpro.baresip"
|
applicationId = "com.tutpro.baresip"
|
||||||
minSdk = 28
|
minSdk = 28
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 543
|
versionCode = 544
|
||||||
versionName = "89.1.0"
|
versionName = "89.1.1"
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
@ -30,7 +30,9 @@ configure<ApplicationExtension> {
|
|||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
ndk { abiFilters.add("x86_64") }
|
ndk {
|
||||||
|
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86_64"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
|
|||||||
@ -85,6 +85,12 @@
|
|||||||
<action android:name="android.intent.action.DIAL" />
|
<action android:name="android.intent.action.DIAL" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="baresip" />
|
||||||
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<action android:name="android.intent.action.DIAL" />
|
<action android:name="android.intent.action.DIAL" />
|
||||||
|
|||||||
@ -69,8 +69,9 @@ sealed class Contact {
|
|||||||
val name = contactWithUri.first.name()
|
val name = contactWithUri.first.name()
|
||||||
if (includeLabel) {
|
if (includeLabel) {
|
||||||
val label = contactWithUri.second.label
|
val label = contactWithUri.second.label
|
||||||
if (label.isNotEmpty()) return "$name $label"
|
if (label.isNotEmpty() && !listOf("SIP", "TEL").contains(label.uppercase()))
|
||||||
if (unique && contactWithUri.first.uris().size > 1)
|
return "$name $label"
|
||||||
|
if (unique || contactWithUri.first.uris().size > 1)
|
||||||
return "$name ${uri.substringAfter(":")}"
|
return "$name ${uri.substringAfter(":")}"
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
@ -83,8 +84,9 @@ sealed class Contact {
|
|||||||
val name = telContactWithUri.first.name()
|
val name = telContactWithUri.first.name()
|
||||||
if (includeLabel) {
|
if (includeLabel) {
|
||||||
val label = telContactWithUri.second.label
|
val label = telContactWithUri.second.label
|
||||||
if (label.isNotEmpty()) return "$name $label"
|
if (label.isNotEmpty() && !listOf("SIP", "TEL").contains(label.uppercase()))
|
||||||
if (unique && telContactWithUri.first.uris().size > 1)
|
return "$name $label"
|
||||||
|
if (unique || telContactWithUri.first.uris().size > 1)
|
||||||
return "$name $userPart"
|
return "$name $userPart"
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,8 @@ import androidx.activity.viewModels
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
@ -176,6 +178,11 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
atStartup = intent.hasExtra("onStartup")
|
atStartup = intent.hasExtra("onStartup")
|
||||||
|
|
||||||
|
if (intent?.action == Intent.ACTION_VIEW &&
|
||||||
|
"baresip".equals(intent.data?.scheme, ignoreCase = true)
|
||||||
|
) {
|
||||||
|
handleProvisioningIntent(this, viewModel, intent)
|
||||||
|
} else {
|
||||||
when (intent?.action) {
|
when (intent?.action) {
|
||||||
ACTION_DIAL, ACTION_CALL, ACTION_VIEW ->
|
ACTION_DIAL, ACTION_CALL, ACTION_VIEW ->
|
||||||
if (BaresipService.isServiceRunning)
|
if (BaresipService.isServiceRunning)
|
||||||
@ -191,6 +198,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
.replace("%20", "")
|
.replace("%20", "")
|
||||||
.filterNot{setOf('-', ' ', '(', ')').contains(it)}
|
.filterNot{setOf('-', ' ', '(', ')').contains(it)}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val permissions = if (Build.VERSION.SDK_INT >= 33)
|
val permissions = if (Build.VERSION.SDK_INT >= 33)
|
||||||
arrayOf(POST_NOTIFICATIONS, RECORD_AUDIO, BLUETOOTH_CONNECT)
|
arrayOf(POST_NOTIFICATIONS, RECORD_AUDIO, BLUETOOTH_CONNECT)
|
||||||
@ -370,6 +378,10 @@ class MainActivity : ComponentActivity() {
|
|||||||
isCallLogIntent(intent) -> {
|
isCallLogIntent(intent) -> {
|
||||||
handleCallLogIntent()
|
handleCallLogIntent()
|
||||||
}
|
}
|
||||||
|
intent.action == Intent.ACTION_VIEW &&
|
||||||
|
intent.data?.scheme.equals("baresip", ignoreCase = true) -> {
|
||||||
|
handleProvisioningIntent(applicationContext, viewModel, intent)
|
||||||
|
}
|
||||||
intent.action in listOf(ACTION_DIAL, ACTION_CALL, ACTION_VIEW) -> {
|
intent.action in listOf(ACTION_DIAL, ACTION_CALL, ACTION_VIEW) -> {
|
||||||
callAction(
|
callAction(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
@ -446,4 +458,36 @@ class MainActivity : ComponentActivity() {
|
|||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleProvisioningIntent(ctx: Context, viewModel: ViewModel, intent: Intent) {
|
||||||
|
val data = intent.data ?: run {
|
||||||
|
Log.w(TAG, "Provisioning intent has no data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val endpoint = data.getQueryParameter("endpoint") ?: return
|
||||||
|
val extension = data.getQueryParameter("extension") ?: return
|
||||||
|
Log.i(TAG, "Provisioning from $endpoint ext=$extension")
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
val payload = Provisioning.fetchAndDecryptBundle(ctx, endpoint, extension)
|
||||||
|
val acc = Provisioning.applyBundle(ctx, payload)
|
||||||
|
if (acc == null) throw Provisioning.ProvisioningException("Failed to apply bundle")
|
||||||
|
Log.i(TAG, "Provisioning applied: ${acc.aor}")
|
||||||
|
viewModel.navigateToHome()
|
||||||
|
if (BaresipService.isServiceRunning) {
|
||||||
|
val restart = Intent(ctx, BaresipService::class.java)
|
||||||
|
restart.action = "Stop"
|
||||||
|
ContextCompat.startForegroundService(ctx, restart)
|
||||||
|
} else {
|
||||||
|
val restartApp = Intent(ctx, MainActivity::class.java)
|
||||||
|
restartApp.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||||
|
ctx.startActivity(restartApp)
|
||||||
|
exitProcess(0)
|
||||||
|
}
|
||||||
|
} catch (e: Provisioning.ProvisioningException) {
|
||||||
|
Log.e(TAG, "Provisioning failed: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
314
app/src/main/kotlin/com/tutpro/baresip/Provisioning.kt
Normal file
314
app/src/main/kotlin/com/tutpro/baresip/Provisioning.kt
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
package com.tutpro.baresip
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import android.security.keystore.KeyGenParameterSpec
|
||||||
|
import android.security.keystore.KeyProperties
|
||||||
|
import android.util.Base64
|
||||||
|
import android.util.Log
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URL
|
||||||
|
import java.security.KeyPairGenerator
|
||||||
|
import java.security.KeyStore
|
||||||
|
import java.security.PrivateKey
|
||||||
|
import java.security.PublicKey
|
||||||
|
import javax.crypto.Cipher
|
||||||
|
import javax.crypto.spec.GCMParameterSpec
|
||||||
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
|
object Provisioning {
|
||||||
|
|
||||||
|
const val ALIAS = "baresip_provisioning"
|
||||||
|
private const val RSA_KEY_SIZE = 2048
|
||||||
|
private const val GCM_TAG_LENGTH = 128
|
||||||
|
private const val SERVER_TIMEOUT_MS = 20_000
|
||||||
|
|
||||||
|
data class BundlePayload(
|
||||||
|
val connectString: String,
|
||||||
|
val clientCertPem: String? = null,
|
||||||
|
val clientKeyPem: String? = null,
|
||||||
|
val caCertsPem: String? = null,
|
||||||
|
val sipVerifyServer: String? = null,
|
||||||
|
val sipTransport: String? = null,
|
||||||
|
val accountName: String? = null,
|
||||||
|
val username: String? = null,
|
||||||
|
val password: String? = null,
|
||||||
|
val displayName: String? = null,
|
||||||
|
val outbound1: String? = null,
|
||||||
|
val outbound2: String? = null,
|
||||||
|
val register: Boolean? = null,
|
||||||
|
val regInt: Int? = null,
|
||||||
|
val checkOrigin: Boolean? = null,
|
||||||
|
val mediaEnc: String? = null,
|
||||||
|
val mediaNat: String? = null,
|
||||||
|
val stunServer: String? = null,
|
||||||
|
val stunUser: String? = null,
|
||||||
|
val stunPass: String? = null,
|
||||||
|
val rtcpMux: Boolean? = null,
|
||||||
|
val rel100: Boolean? = null,
|
||||||
|
val dtmfMode: Int? = null,
|
||||||
|
val answerMode: Int? = null,
|
||||||
|
val autoRedirect: Boolean? = null,
|
||||||
|
val vmUri: String? = null,
|
||||||
|
val countryCode: String? = null,
|
||||||
|
val telProvider: String? = null,
|
||||||
|
val numericKeypad: Boolean? = null,
|
||||||
|
val defaultAccount: Boolean? = null,
|
||||||
|
val customParams: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun hasKeyPair(): Boolean {
|
||||||
|
return try {
|
||||||
|
val ks = KeyStore.getInstance("AndroidKeyStore")
|
||||||
|
ks.load(null)
|
||||||
|
ks.containsAlias(ALIAS)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "hasKeyPair check failed: ${e.message}")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun ensureKeyPair(): PublicKey = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val ks = KeyStore.getInstance("AndroidKeyStore")
|
||||||
|
ks.load(null)
|
||||||
|
if (ks.containsAlias(ALIAS)) {
|
||||||
|
val pub = ks.getCertificate(ALIAS).publicKey
|
||||||
|
return@withContext pub
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "ensureKeyPair reload failed: ${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
val kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA)
|
||||||
|
val spec = KeyGenParameterSpec.Builder(
|
||||||
|
ALIAS,
|
||||||
|
KeyProperties.PURPOSE_DECRYPT or KeyProperties.PURPOSE_ENCRYPT
|
||||||
|
)
|
||||||
|
.setAlgorithmParameterSpec(java.security.spec.RSAKeyGenParameterSpec(RSA_KEY_SIZE, java.security.spec.RSAKeyGenParameterSpec.F4))
|
||||||
|
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
|
||||||
|
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
|
||||||
|
.setRandomizedEncryptionRequired(true)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
kpg.initialize(spec)
|
||||||
|
val kp = kpg.generateKeyPair()
|
||||||
|
kp.public
|
||||||
|
}
|
||||||
|
|
||||||
|
fun publicKeyPem(publicKey: PublicKey): String {
|
||||||
|
val b64 = Base64.encodeToString(publicKey.encoded, Base64.NO_WRAP)
|
||||||
|
return "-----BEGIN PUBLIC KEY-----\n$b64\n-----END PUBLIC KEY-----"
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun fetchAndDecryptBundle(
|
||||||
|
ctx: Context,
|
||||||
|
endpoint: String,
|
||||||
|
extension: String
|
||||||
|
): BundlePayload = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val pub = ensureKeyPair()
|
||||||
|
val enrollment = JSONObject()
|
||||||
|
enrollment.put("extension", extension)
|
||||||
|
enrollment.put("public_key", Base64.encodeToString(pub.encoded, Base64.NO_WRAP))
|
||||||
|
|
||||||
|
val url = Uri.parse(endpoint).buildUpon()
|
||||||
|
.appendPath("bundle")
|
||||||
|
.build()
|
||||||
|
.toString()
|
||||||
|
|
||||||
|
val conn = URL(url).openConnection() as HttpsURLConnection
|
||||||
|
conn.requestMethod = "POST"
|
||||||
|
conn.setRequestProperty("Content-Type", "application/json")
|
||||||
|
conn.doOutput = true
|
||||||
|
conn.connectTimeout = SERVER_TIMEOUT_MS
|
||||||
|
conn.readTimeout = SERVER_TIMEOUT_MS
|
||||||
|
conn.outputStream.use { os ->
|
||||||
|
os.write(enrollment.toString().toByteArray(Charsets.UTF_8))
|
||||||
|
os.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
val code = conn.responseCode
|
||||||
|
if (code !in 200..299) {
|
||||||
|
val err = conn.errorStream?.bufferedReader()?.use { it.readText() } ?: "HTTP $code"
|
||||||
|
throw ProvisioningException("Provisioning failed: $err")
|
||||||
|
}
|
||||||
|
|
||||||
|
val body = conn.inputStream.bufferedReader().use { it.readText() }
|
||||||
|
val root = JSONObject(body)
|
||||||
|
val encryptedKeyB64 = root.optString("encrypted_key")
|
||||||
|
?: throw ProvisioningException("Missing encrypted_key")
|
||||||
|
val ivB64 = root.optString("iv")
|
||||||
|
?: throw ProvisioningException("Missing iv")
|
||||||
|
val ciphertextB64 = root.optString("ciphertext")
|
||||||
|
?: throw ProvisioningException("Missing ciphertext")
|
||||||
|
val tagB64 = root.optString("tag")
|
||||||
|
?: throw ProvisioningException("Missing tag")
|
||||||
|
|
||||||
|
val encryptedKey = Base64.decode(encryptedKeyB64, Base64.NO_WRAP)
|
||||||
|
val iv = Base64.decode(ivB64, Base64.NO_WRAP)
|
||||||
|
val ciphertext = Base64.decode(ciphertextB64, Base64.NO_WRAP)
|
||||||
|
val tag = Base64.decode(tagB64, Base64.NO_WRAP)
|
||||||
|
|
||||||
|
val aesKey = rsaDecrypt(encryptedKey)
|
||||||
|
val plaintext = aesGcmDecrypt(aesKey, iv, ciphertext, tag)
|
||||||
|
val payload = JSONObject(String(plaintext, Charsets.UTF_8))
|
||||||
|
val connectString = payload.optString("connect_string")
|
||||||
|
?: throw ProvisioningException("Missing connect_string in bundle")
|
||||||
|
|
||||||
|
BundlePayload(
|
||||||
|
connectString = connectString,
|
||||||
|
clientCertPem = payload.optString("client_cert", null),
|
||||||
|
clientKeyPem = payload.optString("client_key", null),
|
||||||
|
caCertsPem = payload.optString("ca_certs", null),
|
||||||
|
sipVerifyServer = payload.optString("sip_verify_server"),
|
||||||
|
sipTransport = payload.optString("transport"),
|
||||||
|
accountName = payload.optString("account_name"),
|
||||||
|
username = payload.optString("username"),
|
||||||
|
password = payload.optString("password"),
|
||||||
|
displayName = payload.optString("display_name"),
|
||||||
|
outbound1 = payload.optString("outbound1"),
|
||||||
|
outbound2 = payload.optString("outbound2"),
|
||||||
|
register = if (payload.has("register")) payload.getBoolean("register") else null,
|
||||||
|
regInt = if (payload.has("reg_int")) payload.getInt("reg_int") else null,
|
||||||
|
checkOrigin = if (payload.has("check_origin")) payload.getBoolean("check_origin") else null,
|
||||||
|
mediaEnc = payload.optString("media_enc", null),
|
||||||
|
mediaNat = payload.optString("media_nat", null),
|
||||||
|
stunServer = payload.optString("stun_server", null),
|
||||||
|
stunUser = payload.optString("stun_user", null),
|
||||||
|
stunPass = payload.optString("stun_pass", null),
|
||||||
|
rtcpMux = if (payload.has("rtcp_mux")) payload.getBoolean("rtcp_mux") else null,
|
||||||
|
rel100 = if (payload.has("rel100")) payload.getBoolean("rel100") else null,
|
||||||
|
dtmfMode = if (payload.has("dtmf_mode")) payload.getInt("dtmf_mode") else null,
|
||||||
|
answerMode = if (payload.has("answer_mode")) payload.getInt("answer_mode") else null,
|
||||||
|
autoRedirect = if (payload.has("auto_redirect")) payload.getBoolean("auto_redirect") else null,
|
||||||
|
vmUri = payload.optString("vm_uri", null),
|
||||||
|
countryCode = payload.optString("country_code", null),
|
||||||
|
telProvider = payload.optString("tel_provider", null),
|
||||||
|
numericKeypad = if (payload.has("numeric_keypad")) payload.getBoolean("numeric_keypad") else null,
|
||||||
|
defaultAccount = if (payload.has("default_account")) payload.getBoolean("default_account") else null,
|
||||||
|
customParams = payload.optString("custom_params", null),
|
||||||
|
)
|
||||||
|
} catch (e: ProvisioningException) {
|
||||||
|
throw e
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Provisioning fetch failed", e)
|
||||||
|
throw ProvisioningException("Provisioning error: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun applyBundle(ctx: Context, payload: BundlePayload): Account? = withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val filesPath = BaresipService.filesPath
|
||||||
|
val file = File(filesPath)
|
||||||
|
if (!file.exists()) file.mkdirs()
|
||||||
|
|
||||||
|
var connectString = payload.connectString.trim()
|
||||||
|
val transport = payload.sipTransport?.trim()?.lowercase()
|
||||||
|
if ((transport == "tls" || transport == "wss") && !connectString.contains("transport=")) {
|
||||||
|
connectString = if (connectString.contains("?")) {
|
||||||
|
"$connectString&transport=$transport"
|
||||||
|
} else {
|
||||||
|
"$connectString;transport=$transport"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val existing = Account.ofAor(connectString)
|
||||||
|
val ua = if (existing != null) UserAgent.ofAor(existing.aor) else null
|
||||||
|
val acc = ua?.account ?: run {
|
||||||
|
val aor = if (connectString.startsWith("sip:")) connectString else "sip:$connectString"
|
||||||
|
val uap = UserAgent.uaAlloc(
|
||||||
|
"<$aor>;stunserver=\"stun:stun.l.google.com:19302\";regq=0.5;pubint=0;regint=0;check_origin=no;mwi=no"
|
||||||
|
)
|
||||||
|
if (uap == 0L) return@withContext null
|
||||||
|
UserAgent.ofUap(uap)?.account ?: return@withContext null
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.displayName?.let { acc.displayName = it }
|
||||||
|
payload.username?.let { acc.authUser = it }
|
||||||
|
if (!payload.password.isNullOrBlank()) {
|
||||||
|
BaresipService.aorPasswords[acc.aor] = payload.password
|
||||||
|
}
|
||||||
|
payload.outbound1?.let { if (acc.outbound.size > 0) acc.outbound[0] = it else acc.outbound.add(it) }
|
||||||
|
payload.outbound2?.let { if (acc.outbound.size > 1) acc.outbound[1] = it else if (it.isNotBlank()) acc.outbound.add(it) }
|
||||||
|
if (payload.register != null) {
|
||||||
|
acc.regint = if (payload.register) payload.regInt ?: REGISTRATION_INTERVAL else 0
|
||||||
|
acc.configuredRegInt = payload.regInt ?: REGISTRATION_INTERVAL
|
||||||
|
}
|
||||||
|
payload.checkOrigin?.let { acc.checkOrigin = it }
|
||||||
|
payload.mediaEnc?.let { acc.mediaEnc = it }
|
||||||
|
payload.mediaNat?.let { acc.mediaNat = it }
|
||||||
|
payload.stunServer?.let { acc.stunServer = it }
|
||||||
|
payload.stunUser?.let { acc.stunUser = it }
|
||||||
|
payload.stunPass?.let { acc.stunPass = it }
|
||||||
|
payload.rtcpMux?.let { acc.rtcpMux = it }
|
||||||
|
if (payload.rel100 != null) {
|
||||||
|
acc.rel100Mode = if (payload.rel100) Api.REL100_ENABLED else Api.REL100_DISABLED
|
||||||
|
}
|
||||||
|
payload.dtmfMode?.let { acc.dtmfMode = it }
|
||||||
|
payload.answerMode?.let { acc.answerMode = it }
|
||||||
|
payload.autoRedirect?.let { acc.autoRedirect = it }
|
||||||
|
payload.vmUri?.let { acc.vmUri = it }
|
||||||
|
payload.countryCode?.let { acc.countryCode = it }
|
||||||
|
payload.telProvider?.let { acc.telProvider = it }
|
||||||
|
payload.numericKeypad?.let { acc.numericKeypad = it }
|
||||||
|
payload.defaultAccount?.let { if (it) UserAgent.ofAor(acc.aor)?.makeDefault() }
|
||||||
|
payload.customParams?.let { acc.customParams = it }
|
||||||
|
payload.accountName?.let { acc.nickName = it }
|
||||||
|
|
||||||
|
payload.caCertsPem?.let {
|
||||||
|
File("$filesPath/ca_certs.crt").writeText(it, Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.clientCertPem?.let { cert ->
|
||||||
|
File("$filesPath/cert.pem").writeText(cert, Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.clientKeyPem?.let { key ->
|
||||||
|
File("$filesPath/cert_key.pem").writeText(key, Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!payload.sipVerifyServer.isNullOrBlank()) {
|
||||||
|
val config = File("$filesPath/config")
|
||||||
|
if (config.exists()) {
|
||||||
|
val cfg = config.readText(Charsets.UTF_8)
|
||||||
|
config.writeText(cfg.replace("sip_verify_server ${Config.variable("sip_verify_server")}", "sip_verify_server ${payload.sipVerifyServer}"), Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
Account.saveAccounts()
|
||||||
|
UserAgent.ofAor(acc.aor)?.let { if (acc.regint > 0) it.reRegister() }
|
||||||
|
}
|
||||||
|
|
||||||
|
acc
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to apply bundle", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rsaDecrypt(encrypted: ByteArray): ByteArray {
|
||||||
|
val ks = KeyStore.getInstance("AndroidKeyStore")
|
||||||
|
ks.load(null)
|
||||||
|
val privateKey = ks.getKey(ALIAS, null) as PrivateKey
|
||||||
|
val cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey)
|
||||||
|
return cipher.doFinal(encrypted)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun aesGcmDecrypt(key: ByteArray, iv: ByteArray, ciphertext: ByteArray, tag: ByteArray): ByteArray {
|
||||||
|
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), GCMParameterSpec(GCM_TAG_LENGTH, iv))
|
||||||
|
val combined = ByteArray(ciphertext.size + tag.size)
|
||||||
|
System.arraycopy(ciphertext, 0, combined, 0, ciphertext.size)
|
||||||
|
System.arraycopy(tag, 0, combined, ciphertext.size, tag.size)
|
||||||
|
return cipher.doFinal(combined)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProvisioningException(message: String) : Exception(message)
|
||||||
|
}
|
||||||
2
fastlane/metadata/android/en-US/changelogs/544.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/544.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Show contact name and SIP URI in call URI field if label has not been given
|
||||||
|
- iLBC audio codec now supports both 20 and 30 modes
|
||||||
7
fastlane/metadata/android/ru-RU/changelogs/13.0.0.txt
Normal file
7
fastlane/metadata/android/ru-RU/changelogs/13.0.0.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
- Звук уведомления при сообщении, даже если baresip открыт.
|
||||||
|
- Если имя контакта пустое, использовать его SIP-URI AoR.
|
||||||
|
- Ослаблена проверка имени контакта.
|
||||||
|
- Исправлена редкая ошибка при выборе аккаунта в списке.
|
||||||
|
- Запрос разрешения на запись с микрофона при старте baresip (если не выдано или отклонено навсегда).
|
||||||
|
- Улучшена работа с разрешением на хранилище при бэкапе/восстановлении.
|
||||||
|
- Разрешение на чтение состояния телефона больше не требуется.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/13.0.1.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/13.0.1.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Всегда уведомлять выпадающий список агента пользователя об изменении набора данных при возобновлении
|
||||||
|
главной активности без intent.
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/14.0.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/14.0.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Добавлены символьные аватары для контактов, чатов и истории звонков.
|
||||||
|
- Исправлено сохранение/восстановление контактов с не-ASCII именами.
|
||||||
|
- Улучшено форматирование дат и времени.
|
||||||
|
- Добавлено примечание об ограничении, связанном с несколькими сетевыми интерфейсами.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/15.0.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/15.0.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Добавлены изображения как аватары контактов (альтернатива символьным).
|
||||||
|
- Небольшие улучшения и исправления интерфейса.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/15.1.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/15.1.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Добавлена возможность указать транспортный протокол для AoR учётной записи.
|
||||||
|
- Не показывать порт или транспортный протокол учётной записи, кроме как в окне настроек аккаунта.
|
||||||
6
fastlane/metadata/android/ru-RU/changelogs/16.0.0.txt
Normal file
6
fastlane/metadata/android/ru-RU/changelogs/16.0.0.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- Глобальная настройка "Prefer IPv6" заменена на параметр учётной записи "Prefer IPv6 Media".
|
||||||
|
- Улучшена обработка изменений сетевого подключения.
|
||||||
|
- Порт не требуется в исходящем IPv6-URI.
|
||||||
|
- Сброс аудиофокуса выполняется и при выходе, если не был сделан раньше.
|
||||||
|
- Добавлена начальная поддержка русского языка.
|
||||||
|
- Обновлены некоторые норвежские строки.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/16.0.1.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/16.0.1.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Повторная регистрация UA при появлении новой активной сети или
|
||||||
|
изменении свойств соединения, даже если IP-адреса не изменились.
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/16.1.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/16.1.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Не перерегистрировать учётные записи при изменении свойств соединения, если IP-адреса остались прежними.
|
||||||
|
- Если baresip не запускается, дать пользователю возможность изменить настройки, которые могли вызвать
|
||||||
|
проблему.
|
||||||
|
- Обновления и исправления строк.
|
||||||
8
fastlane/metadata/android/ru-RU/changelogs/17.0.0.txt
Normal file
8
fastlane/metadata/android/ru-RU/changelogs/17.0.0.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
- Исправлено сохранение учётной записи с параметром ;transport в AoR.
|
||||||
|
- Исправлено включение уведомлений при закрытии вызова.
|
||||||
|
- Белый индикатор статуса, если регистрация не включена.
|
||||||
|
- Громкость по умолчанию теперь влияет на голосовые вызовы и музыку.
|
||||||
|
- Улучшен макет и реализация окна учётных записей.
|
||||||
|
- Отладочные сообщения baresip не показываются, если Debug не включён.
|
||||||
|
- Активности не пересоздаются при смене ориентации экрана.
|
||||||
|
- Корректное отображение многострочной информации в чате
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/17.1.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/17.1.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Использовать тип использования вместо типа потока при запросе аудиофокуса.
|
||||||
|
- Исправлено форматирование английского текста помощи для учётной записи.
|
||||||
|
- Не показывать возможный порт AoR при запросе на его удаление.
|
||||||
|
- Индикатор незарегистрированного статуса залит белым цветом.
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/17.2.0.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/17.2.0.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- Имя пользователя для аутентификации теперь по умолчанию равно имени учётной записи.
|
||||||
|
- Запрос пароля при старте baresip, если указано имя пользователя, но пароль отсутствует.
|
||||||
|
- Индикатор статуса учётной записи теперь жёлтый при включённой регистрации в настройках.
|
||||||
|
- Исправлена ошибка создания первой учётной записи на старых версиях Android.
|
||||||
|
- Небольшие улучшения текста.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/17.2.2.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/17.2.2.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Не подписываться на индикацию ожидающих сообщений при создании учётной записи, если URI голосовой почты
|
||||||
|
не задан.
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/17.2.3.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/17.2.3.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Предотвращены вылеты при двойном нажатии на иконки и
|
||||||
|
элементы списка.
|
||||||
|
- Цвет иконки уведомления учётной записи изменён на белый, если она
|
||||||
|
не зарегистрирована.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/17.3.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/17.3.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Добавлен флажок "Показать пароль" в запросе пароля аутентификации.
|
||||||
|
- Запрос разрешения на микрофон сразу при запуске baresip.
|
||||||
|
- Запрещён символ " в пароле аутентификации учётной записи.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/17.4.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/17.4.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Добавлена поддержка Android 10 (API level 29).
|
||||||
|
- Улучшен запрос разрешения на микрофон при первом запуске baresip.
|
||||||
|
- Исправлен вылет при нажатии кнопки вызова без учётных записей.
|
||||||
6
fastlane/metadata/android/ru-RU/changelogs/18.0.0.txt
Normal file
6
fastlane/metadata/android/ru-RU/changelogs/18.0.0.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- Из-за ограничений Android 10 baresip больше не может автоматически
|
||||||
|
запускаться после загрузки без уведомления.
|
||||||
|
- Исправлен перезапуск baresip на Android 10.
|
||||||
|
- Удалена настройка режима ICE Lite в связи с удалением в вышестоящей версии.
|
||||||
|
- Добавлены строки на бразильском португальском из Weblate.
|
||||||
|
- Небольшие исправления в испанских и норвежских строках.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/18.1.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/18.1.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Улучшена настройка аудиокодеков учётной записи.
|
||||||
|
- Всегда показывать входящий вызов (если есть) при возобновлении baresip.
|
||||||
|
- Улучшено и исправлено возобновление на неосновных активностях.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/18.1.2.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/18.1.2.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исправлен вылет при возврате к предыдущей активности после
|
||||||
|
полученного вызова или сообщения.
|
||||||
|
- Улучшена работа с датчиком приближения и громкой связью.
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/19.0.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/19.0.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Добавлена опция медианата TURN для учётной записи.
|
||||||
|
- Добавлена возможность указать имя пользователя/пароль для STUN/TURN сервера.
|
||||||
|
- Строки, связанные с STUN/TURN, для некоторых языков пока не обновлены.
|
||||||
|
- Дополнительные улучшения диалогов.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/20.0.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/20.0.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Улучшения подавления акустического эха.
|
||||||
|
- Настройки звука перенесены из основных настроек в новую активность.
|
||||||
|
- Добавлена настройка расширенного фильтра AEC.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/20.0.1.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/20.0.1.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Исправлен возврат в Audio Activity после паузы.
|
||||||
|
- Исправлено добавление аудиомодулей в настройках звука.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/21.0.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/21.0.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Добавлена начальная поддержка переадресации вызовов, инициируемой baresip.
|
||||||
|
- Добавлен новый язык — португальский из Weblate.
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/21.1.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/21.1.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Добавлена возможность перерегистрации выбранной учётной записи жестом смахивания вниз.
|
||||||
|
- Автоматический фокус и показ мягкой клавиатуры при запросе паролей
|
||||||
|
или адресата переадресации.
|
||||||
|
- Различные исправления, связанные со строками.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/21.2.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/21.2.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Добавлен речевой кодек AMR-WB (Adaptive Multi-Rate Wideband).
|
||||||
|
- Добавлен раздел "Лицензии" в текст "О программе".
|
||||||
|
- Новые переводы на португальский (Бразилия).
|
||||||
7
fastlane/metadata/android/ru-RU/changelogs/23.0.0.txt
Normal file
7
fastlane/metadata/android/ru-RU/changelogs/23.0.0.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
- Добавлен переключатель видимости для паролей аутентификации и STUN/TURN учётной записи
|
||||||
|
- Предпочтение VPN-интерфейса (если есть) при выборе сетевых интерфейсов
|
||||||
|
- Примечание в "О программе" о порядке предпочтения интерфейсов
|
||||||
|
- Улучшена настройка обхода NAT для медиа учётной записи
|
||||||
|
- STUN-сервер Google по умолчанию также при ICE для обхода NAT
|
||||||
|
- Увеличены макс. длины имени пользователя аутентификации, STUN/TURN и отображаемого имени до 64 символов
|
||||||
|
- Добавлены/обновлены переводы на FR, NO и FI
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/23.1.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/23.1.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Добавлен аудиокодек G.729.
|
||||||
|
- Добавлена настройка включения/отключения трассировки SIP-сообщений в logcat.
|
||||||
|
- Схемы URI 'stuns' и 'turns' для STUN/TURN сервера пока не поддерживаются.
|
||||||
|
- Новые переводы на португальский (Бразилия).
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/24.1.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/24.1.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Улучшена обработка клавиш увеличения/уменьшения громкости
|
||||||
|
- Улучшена работа с громкой связью
|
||||||
|
- Новые переводы на русский (RU)
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/24.2.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/24.2.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Автоматический показ мягкой клавиатуры DTMF при подключении вызова
|
||||||
|
- Исправлен вылет при нажатии клавиш громкости вне вызова
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/24.3.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/24.3.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Автоматический показ циферблата только при портретной ориентации устройства
|
||||||
|
- Не воспроизводить звук ожидания вызова при втором входящем вызове
|
||||||
|
- Улучшен текст "О программе"
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/26.0.1.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/26.0.1.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Исправлено включение тёмной темы при запуске приложения baresip
|
||||||
|
- Новые переводы (португальский (Бразилия))
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/26.1.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/26.1.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Другие приложения теперь могут видеть baresip как телефонное приложение для URI sip: и tel:
|
||||||
|
- Улучшено сохранение/восстановление текста URI вызова при паузе главной активности
|
||||||
|
- Добавлен японский перевод
|
||||||
|
- Улучшения цветовой гаммы
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/28.1.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/28.1.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Улучшен поиск контакта, соответствующего SIP-URI
|
||||||
|
- Улучшения стиля панели инструментов и меню
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/29.0.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/29.0.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Добавлена смена учётных записей свайпом влево/вправо
|
||||||
|
- Добавлена настройка режима DTMF для учётной записи
|
||||||
|
- Обновление переводов из Weblate (французский)
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/29.1.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/29.1.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Переводы на португальский (Бразилия) из Weblate
|
||||||
|
- Исправлен тег перевода nb-NO для F-Droid
|
||||||
|
- Устранены предупреждения о 'дублирующем запросе завершения'
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/29.2.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/29.2.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исправления ошибок, связанных с чатом, историей звонков и контактами
|
||||||
|
- Исправлены ошибки автодополнения URI и улучшены связанные с URI проверки
|
||||||
|
- Переводы из Weblate (французский, португальский (Бразилия))
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/3.2.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/3.2.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Добавлена кнопка циферблата для выбора между цифровой и текстовой клавиатурой.
|
||||||
|
- Исправлено автодополнение вызываемого абонента на основе контактов.
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/3.2.2.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/3.2.2.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- Добавлена обработка события неудачной переадресации вызова.
|
||||||
|
- Исправлен вылет при (пере)запуске устройства.
|
||||||
|
- Исправлен вылет при первом возврате из учётных записей в главную активность.
|
||||||
|
- Использован тип ввода "textEmailAddress" для URI учётных записей.
|
||||||
|
- Изменена важность канала уведомлений по умолчанию на низкую.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/30.0.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/30.0.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Обновлена целевая версия SDK до API уровня 30
|
||||||
|
- На Android 10 и выше пользователь выбирает файл при операциях
|
||||||
|
резервного копирования, восстановления и импорта TLS-сертификатов
|
||||||
6
fastlane/metadata/android/ru-RU/changelogs/30.2.0.txt
Normal file
6
fastlane/metadata/android/ru-RU/changelogs/30.2.0.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- Добавлена поддержка эффективного по пропускной способности режима кодека AMR
|
||||||
|
- Разрешены экранированные символы в части пользователя SIP URI и имени пользователя аутентификации
|
||||||
|
- Использование корутины вместо асинхронной задачи для получения конфигурации учётной записи из сети
|
||||||
|
- На Android 10+ используется выборщик файлов для TLS-сертификата и файлов CA
|
||||||
|
- Запрос подтверждения сброса настроек к заводским
|
||||||
|
- Новые переводы (португальский и португальский (Бразилия))
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/30.3.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/30.3.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Воспроизводить звук при автоответе
|
||||||
|
- Удалён кодек iLBC (удалён из вышестоящей версии)
|
||||||
|
- Удалены неиспользуемые аудиофайлы
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/31.0.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/31.0.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Улучшен текст "О программе"
|
||||||
|
- Восстановление позиции списка чатов при возврате из чата
|
||||||
|
- Исправлен вылет при запросе пароля учётной записи
|
||||||
|
- Попытка загрузки модуля iLBC не выполняется
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/31.1.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/31.1.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исправление транспорта websocket в вышестоящей версии
|
||||||
|
- Новые переводы на португальский (Бразилия)
|
||||||
|
- Проверка транспорта в URI исходящего прокси
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/31.2.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/31.2.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Улучшения URI STUN/TURN учётной записи
|
||||||
|
- Различные улучшения, связанные с аудио
|
||||||
|
- Новые переводы на португальский (Бразилия) и словенский
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/32.0.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/32.0.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Добавлена кнопка включения/отключения микрофона во время вызова
|
||||||
|
- Использован горизонтальный скролл для кнопок управления вызовом
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/32.3.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/32.3.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Блокировка WiFi, пока baresip использует сеть WiFi
|
||||||
|
- Восстановлен случайно удалённый файл сигнала обратного вызова
|
||||||
|
- Добавлено примечание в "О программе" об отключении оптимизации батареи
|
||||||
|
- Переводы на шведский язык
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/33.0.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/33.0.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Блокировка WiFi при использовании baresip сети WiFi
|
||||||
|
- Добавлено примечание в "О программе" об оптимизации батареи
|
||||||
|
- Новые переводы на шведский и португальский (Бразилия)
|
||||||
|
- Различные улучшения реализации
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/34.0.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/34.0.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Добавлена ограниченная поддержка нескольких одновременно активных сетевых интерфейсов
|
||||||
|
- Показ уведомления при запуске baresip без доступа к сети
|
||||||
6
fastlane/metadata/android/ru-RU/changelogs/35.0.0.txt
Normal file
6
fastlane/metadata/android/ru-RU/changelogs/35.0.0.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- Использовать фильтр WebRTC Acoustic Echo Cancellation Mobile Mode
|
||||||
|
- Показывать в уведомлении количество пропущенных вызовов, если их более одного
|
||||||
|
- При установке громкости вызова по умолчанию устанавливать и громкость медиа, и вызова
|
||||||
|
- Отменять уведомления при возобновлении главной активности
|
||||||
|
- Исправлена остановка звонка на старых версиях Android
|
||||||
|
- Новые переводы на шведский и португальский (Бразилия)
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/35.1.0.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/35.1.0.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- При включении/отключении aec загружать/выгружать модуль webrtc_aecm
|
||||||
|
- Использовать BaresipService для воспроизведения всех звуков
|
||||||
|
- Корректная обработка ответа о ходе выполнения сессии
|
||||||
|
- Во время вызова клавиши громкости управляют громкостью медиа
|
||||||
|
- Использовать аудиорежим связи, если не в режиме звонка
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/35.2.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/35.2.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исправления и улучшения, связанные с аудиофокусом
|
||||||
|
- Удаление всех пробелов из поля вызываемого абонента
|
||||||
|
- Новый перевод на португальский (Бразилия)
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/36.0.0.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/36.0.0.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- Выполнен переход baresip на API уровня 31 (Android 12)
|
||||||
|
- Улучшено обнаружение доступных сетей
|
||||||
|
- Улучшены запросы разрешений
|
||||||
|
- Удалена настройка учётной записи Prefer IPv6 Media
|
||||||
|
- Новый перевод на португальский (Бразилия)
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/36.1.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/36.1.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Кнопка отключения микрофона перенесена из панели управления вызовом в панель действий
|
||||||
|
- Добавлена настройка оптимизации батареи
|
||||||
|
- Запрос разрешения на запись аудио при запуске baresip
|
||||||
|
- Новые переводы на португальский (Бразилия), французский и шведский
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/36.1.1.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/36.1.1.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Кнопка отключения микрофона перенесена из панели управления вызовом в панель действий
|
||||||
|
- Добавлена настройка оптимизации батареи
|
||||||
|
- Запрос разрешения на запись аудио при запуске baresip
|
||||||
|
- Новые переводы на португальский (Бразилия), французский и шведский
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/36.2.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/36.2.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- В настоящее время иконка микрофона активна только при подключенном вызове
|
||||||
|
- Новые переводы на шведский
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/37.1.0.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/37.1.0.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- Добавлены данные о средней битовой скорости, джиттере, количестве пакетов и потерянных пакетах в информацию о вызове
|
||||||
|
- Использование иконки паузы акцентного цвета для указания, что пользователь поставил вызов на удержание
|
||||||
|
- Уведомление пользователя, когда другая сторона поставила вызов на удержание
|
||||||
|
- Небольшие улучшения, связанные с мягким вводом
|
||||||
|
- Новые переводы на португальский (Бразилия)
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/37.2.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/37.2.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Улучшена защита приложения baresip при блокировке устройства с защищённой блокировкой
|
||||||
|
- Новые переводы на португальский (Бразилия)
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/38.0.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/38.0.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Улучшена обработка блокировки/разблокировки устройства
|
||||||
|
- В настройки добавлена ссылка на настройки Android
|
||||||
|
- Корректная проверка изменения настройки оптимизации батареи
|
||||||
|
- Новые переводы на шведский и португальский (Бразилия)
|
||||||
6
fastlane/metadata/android/ru-RU/changelogs/39.0.0.txt
Normal file
6
fastlane/metadata/android/ru-RU/changelogs/39.0.0.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- Улучшено отображение времени в списке истории вызовов
|
||||||
|
- Добавлена активность с деталями вызова, доступная при касании времени в
|
||||||
|
списке истории вызовов
|
||||||
|
- Исправлено отображение аватаров в списках контактов, вызовов и чатов
|
||||||
|
- Разрешена отмена отвеченного вызова, ожидающего установления
|
||||||
|
- Новые переводы на португальский (Бразилия), шведский и норвежский
|
||||||
6
fastlane/metadata/android/ru-RU/changelogs/39.1.0.txt
Normal file
6
fastlane/metadata/android/ru-RU/changelogs/39.1.0.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- Улучшена и исправлена обработка событий сообщений и переадресации вызовов
|
||||||
|
- Показ уведомления о неудачной регистрации в любой текущей активности
|
||||||
|
- Автоматическое преобразование первых букв предложений в сообщениях в заглавные
|
||||||
|
- Замена устаревших локальных широковещательных рассылок на события LiveData
|
||||||
|
- Исправлены некоторые ошибки, связанные с обработкой внешних действий вызова
|
||||||
|
- Новые переводы на португальский (Бразилия)
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/4.0.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/4.0.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Улучшена реализация контактов, сообщений и истории вызовов.
|
||||||
|
- Исправлен вылет при получении сообщений до добавления учётных записей.
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/4.1.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/4.1.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Все данные, не связанные с пользовательским интерфейсом, теперь хранятся в сервисе baresip, что позволяет корректно восстанавливаться при завершении других активностей baresip системой Android.
|
||||||
|
- Множество других улучшений и исправлений ошибок.
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/4.1.1.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/4.1.1.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исправлена критическая ошибка в проверке разрешения на запись аудио,
|
||||||
|
которая препятствовала запуску новой установки baresip.
|
||||||
|
- Небольшие улучшения.
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/40.0.0.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/40.0.0.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- Добавлен пункт конфигурации учётной записи Telephony Provider
|
||||||
|
- Добавлена поддержка tel URI в качестве значения вызываемого абонента и URI контакта
|
||||||
|
- Запрос учётной записи Telephony Provider у пользователя, если необходимо для совершения вызова
|
||||||
|
- Отображение элементов конфигурации STUN учётной записи только при необходимости
|
||||||
|
- Улучшена обработка действия CALL из других приложений
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/40.0.1.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/40.0.1.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- Добавлен пункт конфигурации учётной записи Telephony Provider
|
||||||
|
- Добавлена поддержка tel URI в качестве значения вызываемого абонента и URI контакта
|
||||||
|
- Запрос учётной записи Telephony Provider у пользователя, если необходимо для совершения вызова
|
||||||
|
- Отображение элементов конфигурации STUN учётной записи только при необходимости
|
||||||
|
- Улучшена обработка действия CALL из других приложений
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/40.1.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/40.1.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Не воспроизводить звук занятости или ошибки при завершении вызова
|
||||||
|
- Повышена надёжность использования Bluetooth
|
||||||
|
- Улучшена обработка событий от ядра baresip
|
||||||
|
- Новые переводы на португальский (Бразилия)
|
||||||
5
fastlane/metadata/android/ru-RU/changelogs/41.0.0.txt
Normal file
5
fastlane/metadata/android/ru-RU/changelogs/41.0.0.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
- Добавлен хронометр времени вызова в строку "Вызов .../Вызов от ..."
|
||||||
|
- Добавлена возможность использования контактов Android
|
||||||
|
- Добавлена настройка "Показывать контакты Android" для выбора отображения контактов Android при нажатии кнопки контактов
|
||||||
|
- Проверка, что файл восстановления создан приложением baresip
|
||||||
|
- Новые переводы на шведский и португальский (Бразилия)
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/42.0.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/42.0.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Настройка 'Показывать контакты Android' заменена настройкой 'Контакты', которая позволяет выбрать, какие контакты используются: baresip, Android или оба
|
||||||
|
- Исправления и улучшения сопоставления имени контакта и URI контакта
|
||||||
|
- Исправлен вылет при принудительном перезапуске приложения baresip системой Android
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/42.2.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/42.2.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Список выбора контактов теперь содержит только те контакты Android, которые имеют ровно один URI
|
||||||
|
- Новые переводы на шведский и португальский (Бразилия)
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/42.3.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/42.3.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исправлено добавление нового контакта baresip
|
||||||
|
- При выборе новой учётной записи по умолчанию порядок остальных не изменяется
|
||||||
|
- Улучшена обработка автоматического отклонения вызовов
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/43.0.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/43.0.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Добавлена начальная поддержка сопровождаемой переадресации вызовов
|
||||||
|
- В активности чата длительное нажатие заменено на короткое
|
||||||
|
- Текст сообщений теперь можно выделять
|
||||||
|
- Использование жирного шрифта в тексте выпадающего списка AoR при активном вызове
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/43.0.2.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/43.0.2.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Добавлена начальная поддержка сопровождаемой переадресации вызовов
|
||||||
|
- В активности чата длительное нажатие заменено на короткое
|
||||||
|
- Текст сообщений теперь можно выделять
|
||||||
|
- Использование жирного шрифта в тексте выпадающего списка AoR при активном вызове
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/43.1.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/43.1.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Исправлена ошибка, связанная с 32-битной архитектурой armeabi-v7a
|
||||||
|
- Отображение "Аноним" или "Неизвестно", если хост URI — anonymous.invalid или unknown.invalid
|
||||||
4
fastlane/metadata/android/ru-RU/changelogs/44.0.0.txt
Normal file
4
fastlane/metadata/android/ru-RU/changelogs/44.0.0.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
- Отображение переадресующего номера, если входящий вызов был переадресован
|
||||||
|
- Исправления, связанные с резервным копированием, на старых версиях Android
|
||||||
|
- Улучшено сопоставление URI с контактом
|
||||||
|
- Новые переводы на португальский (Бразилия)
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/44.1.0.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/44.1.0.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- В соответствии с требованием Google, запрашивать согласие пользователя при выборе контактов Android в настройках
|
||||||
|
- Новые переводы на португальский (Бразилия)
|
||||||
2
fastlane/metadata/android/ru-RU/changelogs/446.txt
Normal file
2
fastlane/metadata/android/ru-RU/changelogs/446.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
- Исправлена проверка режима "Не беспокоить"
|
||||||
|
- Новые переводы
|
||||||
6
fastlane/metadata/android/ru-RU/changelogs/447.txt
Normal file
6
fastlane/metadata/android/ru-RU/changelogs/447.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
- Изменение цвета кнопки вызова на жёлтый, когда кнопка нажата, но вызов ещё не совершён
|
||||||
|
- Не активировать бесполезное программное подавление эха, если аппаратное недоступно
|
||||||
|
- Всегда очищать иконку безопасности и поле DTMF при завершении вызова
|
||||||
|
- Для зарегистрированных учётных записей проверять, что часть пользователя входящего Request URI совпадает с частью пользователя контактного URI REGISTER-запроса
|
||||||
|
- Улучшения буфера дрожания аудио в вышестоящей версии
|
||||||
|
- Новые переводы (французский)
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/448.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/448.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Добавлено примечание о Weblate в текст "О программе"
|
||||||
|
- Новые переводы (китайский)
|
||||||
|
- Исправление макроса логирования в библиотеке baresip
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/449.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/449.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исправлено добавление нового вызова в историю
|
||||||
|
- Устранена "вспышка" экрана при звонке из контактов или истории вызовов
|
||||||
|
- Новые переводы (чешский)
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/45.0.0.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/45.0.0.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Добавлен параметр конфигурации учётной записи "Код страны"
|
||||||
|
- Улучшения, связанные с аудио, из вышестоящей версии
|
||||||
|
- Новые переводы на португальский (Бразилия) и финский
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/45.1.1.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/45.1.1.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Использование протокола установки ключей DTLS на основе эллиптической криптографии
|
||||||
|
- Исправлено резервное копирование истории вызовов
|
||||||
|
- Новые переводы на шведский
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/450.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/450.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Исключить отмеченные звёздочкой контакты Android из режима "Не беспокоить"
|
||||||
|
- Не терять содержимое нового сообщения, которое ещё не было отправлено
|
||||||
|
- Новые переводы (шведский)
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/451.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/451.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Добавлена начальная поддержка динамических цветов на многих экранах
|
||||||
|
- Улучшено отображение и скрытие мягкой клавиатуры
|
||||||
|
- Новые переводы (китайский (упрощённое письмо))
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/452.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/452.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Сохранять изменения учётной записи и настроек до нажатия кнопки "Готово" или "Назад"
|
||||||
|
- Использовать сертификаты TLS CA File также при предварительной настройке учётной записи из сети
|
||||||
|
- Не покидать экран настроек в случае ошибки ввода
|
||||||
1
fastlane/metadata/android/ru-RU/changelogs/453.txt
Normal file
1
fastlane/metadata/android/ru-RU/changelogs/453.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
- Использование цветовой темы Material3 повсеместно
|
||||||
1
fastlane/metadata/android/ru-RU/changelogs/454.txt
Normal file
1
fastlane/metadata/android/ru-RU/changelogs/454.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
- Улучшена видимость поля "Вызов от" на главном экране и поля SIP URI на экране учётной записи
|
||||||
1
fastlane/metadata/android/ru-RU/changelogs/455.txt
Normal file
1
fastlane/metadata/android/ru-RU/changelogs/455.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
- Улучшены цвета контейнеров поверхности
|
||||||
3
fastlane/metadata/android/ru-RU/changelogs/456.txt
Normal file
3
fastlane/metadata/android/ru-RU/changelogs/456.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
- Удалён кодек G.726 из-за большого количества зависимостей
|
||||||
|
- Добавлен кодек G.722 с меньшим количеством зависимостей
|
||||||
|
- Новые переводы (шведский, чешский и китайский)
|
||||||
@ -1,9 +1,13 @@
|
|||||||
Это приложение SIP-клиент для Android, основанный на <a href="https://github.com/baresip/baresip">baresip</a>.
|
Это приложение-агент пользователя для Android, основанное на <a href="https://github.com/baresip/baresip">baresip</a> и поддерживающее SIP- и мобильные голосовые вызовы, а также обмен сообщениями.
|
||||||
|
|
||||||
В настоящее время приложение baresip поддерживает голосовые вызовы, текстовые сообщения, уведомления голосовой почты, а также переводы вызовов «вслепую» и «с участием». Голос может кодироваться с помощью Opus, AMR, GSM, G.729, G.722, G.722.1, G.726 или PCMU/PCMA. Безопасность обеспечивается посредством TLS или WSS для SIP-сигнализации и инкапсуляции мультимедиа в ZRTP или (DTLS) SRTP.
|
В настоящее время baresip поддерживает голосовые вызовы и сообщения через SIP и мобильные сети. Дополнительно при использовании SIP доступны конференц-связь, индикация ожидающих голосовых сообщений (MWI), а также слепая и сопровождаемая переадресация вызовов. Поддержка MMS-сообщений пока отсутствует.
|
||||||
|
|
||||||
Разработка приложения baresip обусловлена необходимостью создания безопасного VoIP клиента на основе SIP с открытым исходным кодом для Android, который не зависит от закрытых сторонних сервисов пуш-уведомлений.
|
В SIP-вызовах аудио может кодироваться с помощью кодеков Opus, AMR, Codec2, G.729, G.722, G.722.1 или PCMU/PCMA. Безопасность обеспечивается за счёт транспорта SIP через TLS или WSS, а также инкапсуляции медиа через ZRTP или SRTP поверх DTLS.
|
||||||
|
|
||||||
Если вам нужны видеозвонки и имеется устройство с Android версии 9 или новее, поддерживающее API Camera2 на третьем или полном уровне аппаратной поддержки, можете вместо этого приложения установить родственное baresip+.
|
Разработка baresip обусловлена потребностью в защищённом, открытом SIP-агенте VoIP для Android, который не зависит от проприетарных сторонних сервисов push-уведомлений. Контакты, мобильные вызовы и SMS-сообщения были добавлены, чтобы сократить количество устанавливаемых приложений.
|
||||||
|
|
||||||
Исходный код доступен на <a href="https://github.com/juha-h/baresip-studio">GitHub</a>, там же можно сообщить о проблемах.
|
Это приложение можно установить на устройствах с Android 9 и выше. Для мобильных вызовов и обмена сообщениями требуется Android 10 или новее.
|
||||||
|
|
||||||
|
Если вам нужны видеозвонки, вместо этого приложения вы можете установить его «родственную» версию — baresip+.
|
||||||
|
|
||||||
|
Исходный код доступен на <a href="https://github.com/juha-h/baresip-studio">GitHub</a>, там же можно сообщать об ошибках.
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
VoIP-клиент для Android, основанный на одноимённой SIP-библиотеке
|
SIP- и мобильный звонки/сообщения, Android-агент на baresip
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user