diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index a339f35e..058d3afc 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -65,6 +65,7 @@ import androidx.compose.runtime.setValue import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat +import androidx.core.net.toUri import androidx.lifecycle.MutableLiveData import androidx.media.AudioAttributesCompat import androidx.media.AudioFocusRequestCompat @@ -83,7 +84,6 @@ class BaresipService: Service() { internal lateinit var intent: Intent private lateinit var am: AudioManager - private lateinit var rt: Ringtone private lateinit var nt: Ringtone private lateinit var nm: NotificationManager private lateinit var snb: NotificationCompat.Builder @@ -131,8 +131,10 @@ class BaresipService: Service() { RingtoneManager.TYPE_NOTIFICATION) nt = RingtoneManager.getRingtone(applicationContext, ntUri) - val rtUri = RingtoneManager.getActualDefaultRingtoneUri(applicationContext, - RingtoneManager.TYPE_RINGTONE) + val rtUri = if (Preferences(applicationContext).ringtoneUri == "") + Settings.System.RINGTONE.toUri() + else + Preferences(applicationContext).ringtoneUri!!.toUri() rt = RingtoneManager.getRingtone(applicationContext, rtUri) nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager @@ -1311,8 +1313,8 @@ class BaresipService: Service() { } private fun startRinging() { - rt.isLooping = true - rt.play() + rt!!.isLooping = true + rt!!.play() if (shouldVibrate()) { vbTimer = Timer() vbTimer!!.schedule(object : TimerTask() { @@ -1346,7 +1348,7 @@ class BaresipService: Service() { } private fun stopRinging() { - rt.stop() + rt!!.stop() if (vbTimer != null) { vbTimer!!.cancel() vbTimer = null @@ -1663,6 +1665,7 @@ class BaresipService: Service() { var aecAvailable = false private var aec: AcousticEchoCanceler? = null var agcAvailable = false + var rt: Ringtone? = null private var agc: AutomaticGainControl? = null private val nsAvailable = NoiseSuppressor.isAvailable() private var ns: NoiseSuppressor? = null diff --git a/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt index 72263ed8..fb7fb8e8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt @@ -6,7 +6,9 @@ import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.os.Build +import android.media.RingtoneManager +import android.net.Uri +import android.os.Build.VERSION import android.os.Bundle import android.os.PowerManager import android.provider.Settings @@ -14,8 +16,10 @@ import android.window.OnBackInvokedCallback import android.window.OnBackInvokedDispatcher import androidx.activity.ComponentActivity import androidx.activity.OnBackPressedCallback +import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.activity.result.ActivityResult import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.RequiresApi @@ -65,6 +69,7 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.content.ContextCompat +import androidx.core.net.toUri import com.tutpro.baresip.CustomElements.AlertDialog import com.tutpro.baresip.CustomElements.Checkbox import com.tutpro.baresip.CustomElements.LabelText @@ -95,6 +100,8 @@ class ConfigActivity : ComponentActivity() { private var newCaFile = false private var oldUserAgent = "" private var newUserAgent = "" + private var oldRingtoneUri = "" + private var newRingtoneUri = "" private var oldBatteryOptimizations = false private var newBatteryOptimizations = false private var oldDefaultDialer = false @@ -208,7 +215,7 @@ class ConfigActivity : ComponentActivity() { enableEdgeToEdge() - if (Build.VERSION.SDK_INT >= 33) + if (VERSION.SDK_INT >= 33) registerBackInvokedCallback() else { onBackPressedCallback = object : OnBackPressedCallback(true) { @@ -274,11 +281,11 @@ class ConfigActivity : ComponentActivity() { ) { Log.d(TAG, "dialerRoleRequest succeeded: " + "${it.resultCode == RESULT_OK}") - if (Build.VERSION.SDK_INT >= 29) + if (VERSION.SDK_INT >= 29) newDefaultDialer = roleManager.isRoleHeld(RoleManager.ROLE_DIALER) } - if (Build.VERSION.SDK_INT >= 29) { + if (VERSION.SDK_INT >= 29) { roleManager = getSystemService(ROLE_SERVICE) as RoleManager oldDefaultDialer = roleManager.isRoleHeld(RoleManager.ROLE_DIALER) } @@ -413,8 +420,9 @@ class ConfigActivity : ComponentActivity() { CaFile(ctx) UserAgent() AudioSettings(ctx) + Ringtone() BatteryOptimizations() - if (Build.VERSION.SDK_INT >= 29) + if (VERSION.SDK_INT >= 29) DefaultDialer() Contacts(ctx) DarkTheme() @@ -628,7 +636,7 @@ class ConfigActivity : ComponentActivity() { tlsCertificateFile = it newTlsCertificateFile = tlsCertificateFile if (it) - if (Build.VERSION.SDK_INT < 29) { + if (VERSION.SDK_INT < 29) { tlsCertificateFile = false when { ContextCompat.checkSelfPermission( @@ -733,7 +741,7 @@ class ConfigActivity : ComponentActivity() { caFile = it newCaFile = caFile if (it) { - if (Build.VERSION.SDK_INT < 29) { + if (VERSION.SDK_INT < 29) { caFile = false when { ContextCompat.checkSelfPermission(ctx, @@ -834,6 +842,54 @@ class ConfigActivity : ComponentActivity() { } } + @Composable + private fun Ringtone() { + oldRingtoneUri = if (Preferences(applicationContext).ringtoneUri == "") + RingtoneManager.getActualDefaultRingtoneUri(applicationContext, RingtoneManager.TYPE_RINGTONE).toString() + else + Preferences(applicationContext).ringtoneUri!! + newRingtoneUri = oldRingtoneUri + val launcher = rememberLauncherForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { result: ActivityResult -> + if (result.resultCode == RESULT_OK) { + val uri: Uri? = if (VERSION.SDK_INT >= 33) + result.data?.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, Uri::class.java) + else + @Suppress("DEPRECATION") + result.data?.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI) + if (uri != null) + newRingtoneUri = uri.toString() + } + } + Row( + Modifier + .fillMaxWidth() + .padding(top = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + Text( + text = stringResource(R.string.ringtone), + modifier = Modifier + .weight(1f) + .clickable { + val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, + RingtoneManager.TYPE_RINGTONE) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getString(R.string.select_ringtone)) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, newRingtoneUri.toUri()) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false) + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true) + launcher.launch(intent) + }, + color = LocalCustomColors.current.itemText, + fontSize = 18.sp, + fontWeight = FontWeight.Bold + ) + } + } + @Composable private fun BatteryOptimizations() { Row( @@ -1240,6 +1296,11 @@ class ConfigActivity : ComponentActivity() { restart = true } + Log.d(TAG, "Old/new ringtone: $oldRingtoneUri / $newRingtoneUri") + if (newRingtoneUri != oldRingtoneUri) { + Preferences(applicationContext).ringtoneUri = newRingtoneUri + BaresipService.rt = RingtoneManager.getRingtone(applicationContext, newRingtoneUri.toUri()) + } if (oldContactsMode != newContactsMode) { Config.replaceVariable("contacts_mode", newContactsMode) BaresipService.contactsMode = newContactsMode @@ -1301,7 +1362,7 @@ class ConfigActivity : ComponentActivity() { } override fun onDestroy() { - if (Build.VERSION.SDK_INT >= 33) { + if (VERSION.SDK_INT >= 33) { if (backInvokedCallback != null) onBackInvokedDispatcher.unregisterOnBackInvokedCallback(backInvokedCallback!!) } diff --git a/app/src/main/kotlin/com/tutpro/baresip/Preferences.kt b/app/src/main/kotlin/com/tutpro/baresip/Preferences.kt index ddb2d54f..d5abef9f 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Preferences.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Preferences.kt @@ -2,6 +2,7 @@ package com.tutpro.baresip import android.content.Context import androidx.preference.PreferenceManager +import androidx.core.content.edit class Preferences(context: Context) { @@ -12,6 +13,9 @@ class Preferences(context: Context) { private val preferences = PreferenceManager.getDefaultSharedPreferences(context) var displayTheme = preferences.getInt(DISPLAY_THEME, -1) - set(value) = preferences.edit().putInt(DISPLAY_THEME, value).apply() + set(value) = preferences.edit() { putInt(DISPLAY_THEME, value) } + + var ringtoneUri = preferences.getString("ringtone_uri", "") + set(value) = preferences.edit() { putString("ringtone_uri", value) } } \ No newline at end of file diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 3dfc6c2b..bd24bd58 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -405,6 +405,8 @@ Videokehysten lähetystaajuus per sekuntti, jota tarjotaan SDP-neuvottelun aikana. Arvon on oltava välillä 10-30. Virheellinen videokehysten lähetystaajuus \'%1$d\' + Soittoääni + Valitse soittoääni User Agent Räätälöity SIP sanoman User-Agent otsikkokentän arvo Virheellinen User-Agent otsikkokentän arvo diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 024580fc..f9e85561 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -378,6 +378,8 @@ Video frame rate that will be offered during the SDP handshake. Valid values are from 10 to 30. Invalid Frames Per Second \'%1$d\' + Ringtone + Select Ringtone User Agent Custom SIP request/response User-Agent header field value Invalid User-Agent header field value