Skip to content

Commit 2d64c04

Browse files
natarajkr007natarajkr
andauthored
Update core-telecom dependency and add CALL_BACK intent filter (#405)
* Update core-telecom dependency and add CALL_BACK intent filter - Update `androidx.core:core-telecom` from `1.0.0-alpha02` to `1.0.1` (latest stable). - Add `android.telecom.action.CALL_BACK` intent filter to the main activity to support integrated call logging. * Update Telecom sample with call log exclusion and callback support - Update: `androidx.core:core-telecom` to `1.1.0-alpha04`. - Add: a UI option to the Telecom sample to exclude calls from the system call log using the `isLogExcluded` property in `CallAttributesCompat`. - Implement handling for `TelecomManager.ACTION_CALL_BACK` in `TelecomCallActivity` to support re-initiating calls from the system UI. - Update Android Gradle Plugin to `8.13.2` and Gradle wrapper to `8.13` to compile against 36.1. - Refactor URI creation to use the `toUri()` extension function. - Update `compileSdk` configuration and add the Foojay toolchain resolver plugin. * Update Telecom call handling and WindowManager initialization - Add `onNewIntent` to `TelecomCallActivity` to handle call-back intents when the activity is already running. - Remove obsolete TODO regarding `isLogExcluded` in `TelecomCallRepository`. - Add `@SuppressLint("RequiresWindowSdk")` to `ExampleWindowInitializer.create` to suppress false positive lint warning. Change-Id: I66df7227042f72d20cd328cac16a8a802385781b * Refactor telecom sample parameters and clean up WindowManager initializer - Update `launchCall` invocations to use named arguments for `excludeCallLogging` to improve readability. - moved `@SuppressLint("RequiresWindowSdk")` annotation in `ExampleWindowInitializer` to a new PR. Change-Id: I9e363e3c3b38ef6c840f23fe4b27df5c5d4a9d94 --------- Co-authored-by: natarajkr <natarajkr@google.com>
1 parent 6daa08a commit 2d64c04

8 files changed

Lines changed: 76 additions & 18 deletions

File tree

gradle/libs.versions.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# limitations under the License.
1515
#
1616
[versions]
17-
agp = "8.9.1"
17+
agp = "8.13.2"
1818
fragmentCompose = "1.8.6"
1919
kotlin = "2.1.10"
2020
coreKtx = "1.17.0"
@@ -66,6 +66,7 @@ playServicesMlkitBarcodeScanning = "18.3.1"
6666
protobuf = "0.9.4"
6767
firebaseCrashlyticsBuildtools = "3.0.5"
6868
uwb = "1.0.0-alpha10"
69+
telecom = "1.1.0-alpha04"
6970

7071

7172
[libraries]
@@ -99,6 +100,7 @@ coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
99100
coil-video = { module = "io.coil-kt:coil-video", version.ref = "coil" }
100101
kotlin-coroutines-play = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "coroutines" }
101102
play-services-location = { module = "com.google.android.gms:play-services-location", version.ref = "play-services-location" }
103+
androidx-core-telecom = { module = "androidx.core:core-telecom", version.ref = "telecom" }
102104

103105
# Core dependencies
104106
android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

samples/connectivity/telecom/build.gradle.kts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@ plugins {
2525

2626
android {
2727
namespace = "com.example.platform.connectivity.telecom"
28-
compileSdk = 36
28+
compileSdk {
29+
version = release(version = 36) {
30+
minorApiLevel = 1
31+
}
32+
}
2933

3034
defaultConfig {
3135
minSdk = 23
32-
targetSdk = 35
3336

3437
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
3538
}
@@ -39,7 +42,6 @@ android {
3942
}
4043

4144
dependencies {
42-
implementation("androidx.core:core-telecom:1.0.1")
4345
implementation(project(mapOf("path" to ":samples:connectivity:audio")))
4446

4547
implementation(libs.androidx.activity.compose)
@@ -50,6 +52,9 @@ dependencies {
5052
implementation(libs.androidx.material3)
5153
implementation(project(":shared"))
5254

55+
// Sample specific dependencies
56+
implementation(libs.androidx.core.telecom)
57+
5358
implementation(libs.accompanist.permissions)
5459

5560
androidTestImplementation(libs.androidx.test.core)

samples/connectivity/telecom/src/main/java/com/example/platform/connectivity/telecom/TelecomCallSample.kt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,21 @@ import android.widget.Toast
2525
import androidx.annotation.RequiresApi
2626
import androidx.compose.foundation.layout.Arrangement
2727
import androidx.compose.foundation.layout.Column
28+
import androidx.compose.foundation.layout.Row
2829
import androidx.compose.foundation.layout.fillMaxSize
2930
import androidx.compose.foundation.layout.padding
3031
import androidx.compose.material3.Button
32+
import androidx.compose.material3.Checkbox
3133
import androidx.compose.material3.MaterialTheme
3234
import androidx.compose.material3.Text
3335
import androidx.compose.runtime.Composable
3436
import androidx.compose.runtime.LaunchedEffect
3537
import androidx.compose.runtime.collectAsState
3638
import androidx.compose.runtime.getValue
39+
import androidx.compose.runtime.mutableStateOf
3740
import androidx.compose.runtime.remember
41+
import androidx.compose.runtime.saveable.rememberSaveable
42+
import androidx.compose.runtime.setValue
3843
import androidx.compose.ui.Alignment
3944
import androidx.compose.ui.Modifier
4045
import androidx.compose.ui.platform.LocalContext
@@ -44,6 +49,7 @@ import com.example.platform.connectivity.telecom.call.TelecomCallService
4449
import com.example.platform.connectivity.telecom.model.TelecomCall
4550
import com.example.platform.connectivity.telecom.model.TelecomCallRepository
4651
import com.example.platform.shared.PermissionBox
52+
import androidx.core.net.toUri
4753

4854
@RequiresApi(Build.VERSION_CODES.O)
4955
@Composable
@@ -104,14 +110,30 @@ private fun TelecomCallOptions() {
104110
"No active call"
105111
}
106112
Text(text = title, style = MaterialTheme.typography.titleLarge)
113+
114+
var excludeCallLogging by rememberSaveable {
115+
mutableStateOf(false)
116+
}
117+
Row(
118+
verticalAlignment = Alignment.CenterVertically
119+
) {
120+
Checkbox(
121+
checked = excludeCallLogging,
122+
onCheckedChange = { isChecked ->
123+
excludeCallLogging = isChecked
124+
}
125+
)
126+
Text("Exclude from call logs")
127+
}
107128
Button(
108129
enabled = !hasOngoingCall,
109130
onClick = {
110131
Toast.makeText(context, "Incoming call in 2 seconds", Toast.LENGTH_SHORT).show()
111132
context.launchCall(
112133
action = TelecomCallService.ACTION_INCOMING_CALL,
113134
name = "Alice",
114-
uri = Uri.parse("tel:12345"),
135+
uri = "tel:12345".toUri(),
136+
excludeCallLogging = excludeCallLogging
115137
)
116138
},
117139
) {
@@ -123,7 +145,8 @@ private fun TelecomCallOptions() {
123145
context.launchCall(
124146
action = TelecomCallService.ACTION_OUTGOING_CALL,
125147
name = "Bob",
126-
uri = Uri.parse("tel:54321"),
148+
uri = "tel:54321".toUri(),
149+
excludeCallLogging = excludeCallLogging
127150
)
128151
},
129152
) {
@@ -133,12 +156,13 @@ private fun TelecomCallOptions() {
133156
}
134157

135158
@RequiresApi(Build.VERSION_CODES.O)
136-
private fun Context.launchCall(action: String, name: String, uri: Uri) {
159+
internal fun Context.launchCall(action: String, name: String, uri: Uri, excludeCallLogging: Boolean) {
137160
startService(
138161
Intent(this, TelecomCallService::class.java).apply {
139162
this.action = action
140163
putExtra(TelecomCallService.EXTRA_NAME, name)
141164
putExtra(TelecomCallService.EXTRA_URI, uri)
165+
putExtra(TelecomCallService.EXTRA_EXCLUDE_CALL_LOGGING, excludeCallLogging)
142166
},
143167
)
144168
}

samples/connectivity/telecom/src/main/java/com/example/platform/connectivity/telecom/call/TelecomCallActivity.kt

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import android.app.KeyguardManager
2020
import android.content.Intent
2121
import android.os.Build
2222
import android.os.Bundle
23+
import android.telecom.TelecomManager
2324
import android.util.Log
2425
import android.view.WindowManager
2526
import androidx.activity.ComponentActivity
@@ -31,6 +32,8 @@ import androidx.compose.material3.MaterialTheme
3132
import androidx.compose.material3.Surface
3233
import androidx.compose.ui.Modifier
3334
import androidx.core.content.getSystemService
35+
import androidx.core.net.toUri
36+
import com.example.platform.connectivity.telecom.launchCall
3437
import com.example.platform.connectivity.telecom.model.TelecomCallRepository
3538

3639

@@ -50,6 +53,8 @@ class TelecomCallActivity : ComponentActivity() {
5053
// Set the right flags for a call type activity.
5154
setupCallActivity()
5255

56+
handleCallBack()
57+
5358
setContent {
5459
MaterialTheme {
5560
Surface(
@@ -78,6 +83,12 @@ class TelecomCallActivity : ComponentActivity() {
7883
)
7984
}
8085

86+
override fun onNewIntent(intent: Intent) {
87+
super.onNewIntent(intent)
88+
setIntent(intent)
89+
handleCallBack()
90+
}
91+
8192
/**
8293
* Enable the calling activity to be shown in the lockscreen and dismiss the keyguard to enable
8394
* users to answer without unblocking.
@@ -94,8 +105,17 @@ class TelecomCallActivity : ComponentActivity() {
94105
}
95106

96107
val keyguardManager = getSystemService<KeyguardManager>()
97-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && keyguardManager != null) {
98-
keyguardManager.requestDismissKeyguard(this, null)
108+
keyguardManager?.requestDismissKeyguard(this, null)
109+
}
110+
111+
private fun handleCallBack() {
112+
if (intent.action == TelecomManager.ACTION_CALL_BACK) {
113+
launchCall(
114+
action = TelecomCallService.ACTION_OUTGOING_CALL,
115+
name = "Bob",
116+
uri = "tel:54321".toUri(),
117+
excludeCallLogging = false
118+
)
99119
}
100120
}
101121
}

samples/connectivity/telecom/src/main/java/com/example/platform/connectivity/telecom/call/TelecomCallService.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class TelecomCallService : Service() {
5959
companion object {
6060
internal const val EXTRA_NAME: String = "extra_name"
6161
internal const val EXTRA_URI: String = "extra_uri"
62+
internal const val EXTRA_EXCLUDE_CALL_LOGGING = "extra_exclude_call_logging"
6263
internal const val ACTION_INCOMING_CALL = "incoming_call"
6364
internal const val ACTION_OUTGOING_CALL = "outgoing_call"
6465
internal const val ACTION_UPDATE_CALL = "update_call"
@@ -124,6 +125,7 @@ class TelecomCallService : Service() {
124125
@Suppress("DEPRECATION")
125126
intent.getParcelableExtra(EXTRA_URI)!!
126127
}
128+
val excludeCallLogging = intent.getBooleanExtra(EXTRA_EXCLUDE_CALL_LOGGING, false)
127129

128130
scope.launch {
129131
if (incoming) {
@@ -133,7 +135,7 @@ class TelecomCallService : Service() {
133135

134136
launch {
135137
// Register the call with the Telecom stack
136-
telecomRepository.registerCall(name, uri, incoming)
138+
telecomRepository.registerCall(name, uri, excludeCallLogging, incoming)
137139
}
138140

139141
if (!incoming) {

samples/connectivity/telecom/src/main/java/com/example/platform/connectivity/telecom/model/TelecomCallRepository.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,7 @@ import androidx.annotation.RequiresApi
2525
import androidx.core.telecom.CallAttributesCompat
2626
import androidx.core.telecom.CallControlResult
2727
import androidx.core.telecom.CallControlScope
28-
import androidx.core.telecom.CallException
2928
import androidx.core.telecom.CallsManager
30-
import kotlinx.coroutines.CoroutineScope
31-
import kotlinx.coroutines.Dispatchers
32-
import kotlinx.coroutines.SupervisorJob
3329
import kotlinx.coroutines.channels.Channel
3430
import kotlinx.coroutines.flow.Flow
3531
import kotlinx.coroutines.flow.MutableStateFlow
@@ -87,8 +83,13 @@ class TelecomCallRepository(private val callsManager: CallsManager) {
8783
* Register a new call with the provided attributes.
8884
* Use the [currentCall] StateFlow to receive status updates and process call related actions.
8985
*/
90-
suspend fun registerCall(displayName: String, address: Uri, isIncoming: Boolean) {
91-
// For simplicity we don't support multiple calls
86+
suspend fun registerCall(
87+
displayName: String,
88+
address: Uri,
89+
excludeCallLogging: Boolean,
90+
isIncoming: Boolean
91+
) {
92+
// For simplicity, we don't support multiple calls
9293
check(_currentCall.value !is TelecomCall.Registered) {
9394
"There cannot be more than one call at the same time."
9495
}
@@ -97,6 +98,7 @@ class TelecomCallRepository(private val callsManager: CallsManager) {
9798
val attributes = CallAttributesCompat(
9899
displayName = displayName,
99100
address = address,
101+
isLogExcluded = excludeCallLogging,
100102
direction = if (isIncoming) {
101103
CallAttributesCompat.DIRECTION_INCOMING
102104
} else {
@@ -221,7 +223,7 @@ class TelecomCallRepository(private val callsManager: CallsManager) {
221223
}
222224

223225
is TelecomCallAction.ToggleMute -> {
224-
// We cannot programmatically mute the telecom stack. Instead we just update
226+
// We cannot programmatically mute the telecom stack. Instead, we just update
225227
// the state of the call and this will start/stop audio capturing.
226228
updateCurrentCall {
227229
copy(isMuted = !isMuted)

settings.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ pluginManagement {
2727
gradlePluginPortal()
2828
}
2929
}
30+
plugins {
31+
id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0"
32+
}
3033
dependencyResolutionManagement {
3134
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3235
repositories {

0 commit comments

Comments
 (0)