Skip to content

Commit a509daf

Browse files
authored
Merge pull request #307 from bazl-E/more_phone_support
feat: enhance phone account settings handling for various manufacturers
2 parents e6483e2 + 2e08483 commit a509daf

File tree

1 file changed

+121
-18
lines changed

1 file changed

+121
-18
lines changed

android/src/main/kotlin/com/twilio/twilio_voice/types/TelecomManagerExtension.kt

Lines changed: 121 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ import android.app.Activity
44
import android.content.ComponentName
55
import android.content.Context
66
import android.content.Intent
7+
import android.content.pm.ApplicationInfo
8+
import android.content.pm.PackageManager
79
import android.graphics.drawable.Icon
810
import android.os.Build
11+
import android.provider.Settings
12+
import java.util.Locale
913
import android.telecom.PhoneAccount
1014
import android.telecom.PhoneAccountHandle
1115
import android.telecom.TelecomManager
@@ -60,27 +64,126 @@ object TelecomManagerExtension {
6064
}
6165

6266
fun TelecomManager.openPhoneAccountSettings(activity: Activity) {
63-
if (Build.MANUFACTURER.equals("Samsung", ignoreCase = true)|| Build.MANUFACTURER.equals("OnePlus", ignoreCase = true)) {
64-
try {
65-
val intent = Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS)
66-
intent.component = ComponentName(
67-
"com.android.server.telecom",
68-
"com.android.server.telecom.settings.EnableAccountPreferenceActivity"
69-
)
70-
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
71-
activity.startActivity(intent, null)
72-
} catch (e: Exception) {
73-
Log.e("TelecomManager", "openPhoneAccountSettings: ${e.message}")
74-
75-
// use fallback method
76-
val intent = Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS)
77-
activity.startActivity(intent, null)
67+
if (launchTelecomEnablePreference(activity)) {
68+
return
69+
}
70+
71+
val packageManager = activity.packageManager
72+
val candidateIntents = buildList {
73+
addAll(manufacturerSpecificIntents(activity))
74+
add(Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS))
75+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
76+
add(Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS))
77+
}
78+
add(Intent(Settings.ACTION_SETTINGS))
79+
}
80+
81+
candidateIntents.forEach { baseIntent ->
82+
val intent = Intent(baseIntent).apply {
83+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
84+
if (component == null) {
85+
resolveSystemComponent(packageManager, baseIntent)?.let { component = it }
86+
}
87+
}
88+
89+
if (canHandleIntent(packageManager, intent)) {
90+
try {
91+
activity.startActivity(intent)
92+
return
93+
} catch (error: Exception) {
94+
Log.w("TelecomManager", "openPhoneAccountSettings: failed to launch ${intent.action}: ${error.message}")
95+
}
96+
}
97+
}
98+
99+
Log.e("TelecomManager", "openPhoneAccountSettings: Unable to find compatible settings activity.")
100+
}
101+
102+
private fun TelecomManager.launchTelecomEnablePreference(activity: Activity): Boolean {
103+
val manufacturer = Build.MANUFACTURER?.lowercase(Locale.US).orEmpty()
104+
val brand = Build.BRAND?.lowercase(Locale.US).orEmpty()
105+
val targets = setOf("samsung", "oneplus", "realme", "oppo")
106+
107+
if (manufacturer !in targets && brand !in targets) {
108+
return false
109+
}
110+
111+
val baseIntent = Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS).apply {
112+
component = ComponentName(
113+
"com.android.server.telecom",
114+
"com.android.server.telecom.settings.EnableAccountPreferenceActivity"
115+
)
116+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
117+
}
118+
119+
return try {
120+
activity.startActivity(baseIntent)
121+
true
122+
} catch (error: Exception) {
123+
Log.w(
124+
"TelecomManager",
125+
"launchTelecomEnablePreference: primary component failed: ${error.message}"
126+
)
127+
128+
tryLegacyTelecomIntent(activity)
129+
}
130+
}
131+
132+
private fun tryLegacyTelecomIntent(activity: Activity): Boolean {
133+
return try {
134+
val fallbackIntent = Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS).apply {
135+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
78136
}
137+
activity.startActivity(fallbackIntent)
138+
true
139+
} catch (fallbackError: Exception) {
140+
Log.w(
141+
"TelecomManager",
142+
"tryLegacyTelecomIntent: fallback intent failed: ${fallbackError.message}"
143+
)
144+
false
145+
}
146+
}
147+
148+
private fun manufacturerSpecificIntents(activity: Activity): List<Intent> {
149+
val manufacturer = Build.MANUFACTURER?.lowercase(Locale.US).orEmpty()
150+
val brand = Build.BRAND?.lowercase(Locale.US).orEmpty()
151+
152+
if (manufacturer !in setOf("oppo", "realme") && brand !in setOf("oppo", "realme")) {
153+
return emptyList()
154+
}
155+
156+
val components = listOf(
157+
ComponentName("com.android.settings", "com.android.settings.Settings\$DefaultAppSettingsActivity"),
158+
ComponentName("com.coloros.phonemanager", "com.coloros.phonemanager.defaultapp.DefaultAppManagerActivity"),
159+
ComponentName("com.coloros.phonemanager", "com.coloros.phonemanager.defaultapp.DefaultAppListActivity"),
160+
ComponentName("com.coloros.phonemanager", "com.coloros.phonemanager.defaultapp.DefaultAppEntryActivity")
161+
)
79162

80-
} else {
81-
val intent = Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS)
82-
activity.startActivity(intent, null)
163+
val explicitIntents = components.map { componentName ->
164+
Intent(Intent.ACTION_VIEW).apply { component = componentName }
83165
}
166+
167+
val packagedDefaultAppsIntent = Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS).apply {
168+
`package` = "com.android.settings"
169+
}
170+
171+
return explicitIntents + packagedDefaultAppsIntent
172+
}
173+
174+
private fun resolveSystemComponent(packageManager: PackageManager, intent: Intent): ComponentName? {
175+
val matches = packageManager.queryIntentActivities(intent, 0)
176+
val preferred = matches.firstOrNull { resolveInfo ->
177+
resolveInfo.activityInfo?.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM) != 0
178+
} ?: matches.firstOrNull()
179+
180+
return preferred?.activityInfo?.let { activityInfo ->
181+
ComponentName(activityInfo.packageName, activityInfo.name)
182+
}
183+
}
184+
185+
private fun canHandleIntent(packageManager: PackageManager, intent: Intent): Boolean {
186+
return intent.resolveActivity(packageManager) != null
84187
}
85188

86189

0 commit comments

Comments
 (0)