1

背景

我正在开发一个实现InCallService的应用程序,因此它可以处理电话

问题

在具有多 SIM 卡的设备上,我需要显示(当前设备的)使用了哪个 SIM 卡和相关电话号码的信息。

问题是,我找不到从哪里获得这些信息。

我发现了什么

  1. 鉴于我达到了onCallAdded之类的函数,我得到了一个Call类的实例,所以我需要将我从那里得到的东西关联到一个 sim 插槽和电话号码。

  2. 使用call.getDetails().getHandle(),我可以得到一个 Uri,它只包含另一个打电话的人(打电话给当前用户,或者当前用户打电话给谁)的电话号码。

  3. 我可以遍历所有 SIM 卡,但找不到可以用来在它们和当前通话之间映射的内容:

final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
for (final SubscriptionInfo subscriptionInfo : subscriptionManager.getActiveSubscriptionInfoList()) {
    final TelephonyManager subscriptionId = telephonyManager.createForSubscriptionId(subscriptionInfo.getSubscriptionId());
}
  1. 有一个旧代码不再起作用,它使用call.getDetails().getAccountHandle().getId()and SubscriptionManager.from(context)getActiveSubscriptionInfoList().getActiveSubscriptionInfoList()

  2. 我想我可以使用telephonyManager.getSubscriptionId(callDetails.getAccountHandle()),但它需要 API 30,这是相当新的......

问题

给定我从这个回调(可能还有其他)中接到的电话,我怎样才能获得相关的 SIM 卡插槽和电话号码?

我更喜欢知道如何为尽可能广泛的 Android 版本做到这一点,因为 InCallService 来自 API 23……在 API 30 之前应该可以,对吧?

4

1 回答 1

0

用于call.getDetails().getAccountHandle()获取PhoneAccountHandle

然后使用TelecomManager.getPhoneAccount()获取PhoneAccount实例。


Manifest.permission.READ_PHONE_NUMBERS针对 API 级别 31+ 的应用程序需要权限。


免责声明:我不是 Android 专家,所以请验证我的想法。


编辑:因此 API 30 之前和 API 30 之前的解决方案可能是这样的:

@RequiresApi(Build.VERSION_CODES.M)
fun handleCall(context: Context, call: Call) {
    var foundAndSetSimDetails = false
    val callDetailsAccountHandle = callDetails.accountHandle
    val subscriptionManager = context
        .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
    val telephonyManager =
        context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    val telecomManager =
        context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
    val hasReadPhoneStatePermission =
        ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == android.content.pm.PackageManager.PERMISSION_GRANTED
    val phoneAccount = telecomManager.getPhoneAccount(callDetailsAccountHandle)
    //TODO when targeting API 31, we might need to check for a new permission here, of READ_PHONE_NUMBERS
    //find SIM by phone account
    if (!foundAndSetSimDetails && phoneAccount != null && hasReadPhoneStatePermission) {
        val callCapablePhoneAccounts = telecomManager.callCapablePhoneAccounts
        run {
            callCapablePhoneAccounts?.forEachIndexed { index, phoneAccountHandle ->
                if (phoneAccountHandle != callDetailsAccountHandle)
                    return@forEachIndexed
                if (!phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION))
                    return@run
                //found the sim card index
                simName = phoneAccount.label?.toString().orEmpty()
                simIndex = index + 1
                foundAndSetSimDetails = true
                return@run
            }
        }
    }
    //find SIM by subscription ID
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && hasReadPhoneStatePermission) {
        try {
            val callSubscriptionId: Int =
                telephonyManager.getSubscriptionId(callDetailsAccountHandle!!)
            for (subscriptionInfo: SubscriptionInfo in subscriptionManager.activeSubscriptionInfoList) {
                val activeSubscriptionId: Int = subscriptionInfo.subscriptionId
                if (activeSubscriptionId == callSubscriptionId) {
                    setSimDetails(telephonyManager, subscriptionInfo)
                    foundAndSetSimDetails = true
                    break
                }
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }
    //find SIM by phone number
    if (!foundAndSetSimDetails && hasReadPhoneStatePermission) {
        try {
            val simPhoneNumber: String? = phoneAccount?.address?.schemeSpecificPart
            if (!simPhoneNumber.isNullOrBlank()) {
                for (subscriptionInfo in subscriptionManager.activeSubscriptionInfoList) {
                    if (simPhoneNumber == subscriptionInfo.number) {
                        setSimDetails(telephonyManager, subscriptionInfo)
                        foundAndSetSimDetails = true
                        break
                    }
                }
                if (!foundAndSetSimDetails)
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    private fun setSimDetails(telephonyManager: TelephonyManager, subscriptionInfo: SubscriptionInfo) {
        var foundSimName: String? = null
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            val telephonyManagerForSubscriptionId =
                telephonyManager.createForSubscriptionId(subscriptionInfo.subscriptionId)
            foundSimName = telephonyManagerForSubscriptionId.simOperatorName
        }
        if (foundSimName.isNullOrBlank())
            foundSimName = subscriptionInfo.carrierName?.toString()
        simName = if (foundSimName.isNullOrBlank())
            ""
        else foundSimName
        simIndex = subscriptionInfo.simSlotIndex + 1
    }
于 2021-11-07T23:33:16.947 回答