Add baresip:// provisioning link support via encrypted bundle fetch

This commit is contained in:
2026-08-18 19:35:20 +01:00
parent 11619a9130
commit 77bfe351f2
4 changed files with 381 additions and 15 deletions

View File

@ -31,6 +31,8 @@ import androidx.activity.viewModels
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.LaunchedEffect
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
@ -176,20 +178,26 @@ class MainActivity : ComponentActivity() {
atStartup = intent.hasExtra("onStartup")
when (intent?.action) {
ACTION_DIAL, ACTION_CALL, ACTION_VIEW ->
if (BaresipService.isServiceRunning)
callAction(
applicationContext,
viewModel,
intent.data,
if (intent?.action == ACTION_CALL) "call" else "dial"
)
else
BaresipService.callActionUri = intent.data
.toString().replace("%2B", "+")
.replace("%20", "")
.filterNot{setOf('-', ' ', '(', ')').contains(it)}
if (intent?.action == Intent.ACTION_VIEW &&
"baresip".equals(intent.data?.scheme, ignoreCase = true)
) {
handleProvisioningIntent(this, viewModel, intent)
} else {
when (intent?.action) {
ACTION_DIAL, ACTION_CALL, ACTION_VIEW ->
if (BaresipService.isServiceRunning)
callAction(
applicationContext,
viewModel,
intent.data,
if (intent?.action == ACTION_CALL) "call" else "dial"
)
else
BaresipService.callActionUri = intent.data
.toString().replace("%2B", "+")
.replace("%20", "")
.filterNot{setOf('-', ' ', '(', ')').contains(it)}
}
}
val permissions = if (Build.VERSION.SDK_INT >= 33)
@ -370,6 +378,10 @@ class MainActivity : ComponentActivity() {
isCallLogIntent(intent) -> {
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) -> {
callAction(
applicationContext,
@ -446,4 +458,36 @@ class MainActivity : ComponentActivity() {
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}")
}
}
}
}