@@ -4,8 +4,12 @@ import android.app.Activity
44import android.content.ComponentName
55import android.content.Context
66import android.content.Intent
7+ import android.content.pm.ApplicationInfo
8+ import android.content.pm.PackageManager
79import android.graphics.drawable.Icon
810import android.os.Build
11+ import android.provider.Settings
12+ import java.util.Locale
913import android.telecom.PhoneAccount
1014import android.telecom.PhoneAccountHandle
1115import 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