如何在onCallAdded回调中获取当前设备的phone号码和SIM卡槽?
How to get the phone number and SIM card slot for the current device, on the callback of onCallAdded?
背景
我正在开发一个实现 InCallService 的应用程序,因此它可以处理 phone 个调用
问题
在具有多 SIM 卡的设备上,我需要显示使用了哪个 SIM 卡和关联的 phone 号码(当前设备)的信息。
问题是,我找不到从哪里获得这些信息。
我发现了什么
鉴于我达到了像 onCallAdded, I get an instance of Call class 这样的功能,所以我需要将我从那里得到的东西关联到 sim 插槽和 phone 号码.
使用 call.getDetails().getHandle()
,我可以获得一个 Uri,它只包含另一个呼叫者的 phone 号码(谁呼叫了当前用户,或者当前用户有谁称为)。
我可以遍历所有 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());
}
有一个旧代码不再有效,它使用 call.getDetails().getAccountHandle().getId()
和 SubscriptionManager.from(context)getActiveSubscriptionInfoList().getActiveSubscriptionInfoList()
。
我想我可以使用 telephonyManager.getSubscriptionId(callDetails.getAccountHandle())
,但它需要 API 30,这是相当新的...
问题
鉴于我从此回调(可能还有其他回调)收到的 phone 电话,我如何才能获得相关联的 SIM 插槽和它的 phone 号码?
我更想知道如何为尽可能广泛的 Android 版本做到这一点,因为 InCallService 来自 API 23...在 API 之前应该是可能的30 岁吧?
使用call.getDetails().getAccountHandle()
得到PhoneAccountHandle。
然后使用TelecomManager.getPhoneAccount() to get PhoneAccount实例。
针对 API 级别 31+ 的应用程序需要权限 Manifest.permission.READ_PHONE_NUMBERS
。
免责声明:我不是 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
}
背景
我正在开发一个实现 InCallService 的应用程序,因此它可以处理 phone 个调用
问题
在具有多 SIM 卡的设备上,我需要显示使用了哪个 SIM 卡和关联的 phone 号码(当前设备)的信息。
问题是,我找不到从哪里获得这些信息。
我发现了什么
鉴于我达到了像 onCallAdded, I get an instance of Call class 这样的功能,所以我需要将我从那里得到的东西关联到 sim 插槽和 phone 号码.
使用
call.getDetails().getHandle()
,我可以获得一个 Uri,它只包含另一个呼叫者的 phone 号码(谁呼叫了当前用户,或者当前用户有谁称为)。我可以遍历所有 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());
}
有一个旧代码不再有效,它使用
call.getDetails().getAccountHandle().getId()
和SubscriptionManager.from(context)getActiveSubscriptionInfoList().getActiveSubscriptionInfoList()
。我想我可以使用
telephonyManager.getSubscriptionId(callDetails.getAccountHandle())
,但它需要 API 30,这是相当新的...
问题
鉴于我从此回调(可能还有其他回调)收到的 phone 电话,我如何才能获得相关联的 SIM 插槽和它的 phone 号码?
我更想知道如何为尽可能广泛的 Android 版本做到这一点,因为 InCallService 来自 API 23...在 API 之前应该是可能的30 岁吧?
使用call.getDetails().getAccountHandle()
得到PhoneAccountHandle。
然后使用TelecomManager.getPhoneAccount() to get PhoneAccount实例。
针对 API 级别 31+ 的应用程序需要权限 Manifest.permission.READ_PHONE_NUMBERS
。
免责声明:我不是 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
}