简体   繁体   English

使用双SIM卡功能时如何获取PhoneStateListener

[英]How to get a PhoneStateListener when using Dual SIM functionality

so I am currently implementing a call forwarding feature in Android, for dual SIM devices. 因此,我目前正在Android中为双SIM卡设备实现呼叫转移功能。 In order to read the current state of the call forwarding (enabled/disabled) for a SIM card, I do the following: 为了读取SIM卡的呼叫转移的当前状态(启用/禁用),请执行以下操作:

  1. I create a TelephonyManager object: 我创建一个TelephonyManager对象:

val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager

  1. I create a PhoneStateListener object and override the onCallForwardingIndicatorChanged method: 我创建一个PhoneStateListener对象,并重写onCallForwardingIndicatorChanged方法:

     val myPhoneStateListener = object: PhoneStateListener() { override fun onCallForwardingIndicatorChanged(isCallForwardingEnabled: Boolean) { if(isCallForwardingEnabled) println("Call forwarding enabled!") else println("Call forwarding disabled!") } } 
  2. I registered the PhoneStateListener : 我注册了PhoneStateListener

telephonyManager.listen(myPhoneStateListener, LISTEN_CALL_FORWARDING_INDICATOR)

This works perfectly fine for the primary (the first) SIM card. 这对于主(第一个)SIM卡非常有效。

But I am having trouble doing the same for the second SIM card. 但是我在第二张SIM卡上也做不到。 Here is how I am trying to do it: 这是我尝试执行的操作:

  1. I use a SubscriptionManager object to retrieve the subscriptionId of the second SIM card: 我使用SubscriptionManager对象检索第二张SIM卡的subscriptionId:

     val subscriptionManager = getSystemService(TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager val subscriptionIdOfSimCard2 = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(1).subscriptionId 
  2. I create a separate TelephonyManager for the second SIM card, with the correct subscriptionId: 我为第二张SIM卡创建一个单独的TelephonyManager ,具有正确的subscriptionId:

     val secondTelephonyManager = (getSystemService(TELEPHONY_SERVICE) as TelephonyManager).createForSubscriptionId(subscriptionIdOfSimCard2) 
  3. I create a second PhoneStateListener , just like the one for the first SIM card, lets call it mySecondPhoneStateListener and register it with the second TelephonyManager : 我创建了第二个PhoneStateListener ,就像第一个SIM卡的那个mySecondPhoneStateListener ,我们将其mySecondPhoneStateListener并在第二个TelephonyManager注册:

     secondTelephonyManager.listen(mySecondPhoneStateListener, LISTEN_CALL_FORWARDING_INDICATOR) 

The problem now is, that in mySecondPhoneStateListener I don't get callbacks for the second SIM card, but still the primary, first one. 现在的问题是,在mySecondPhoneStateListener中,我没有获得第二张SIM卡的回调,但是仍然获得了第一张SIM卡的回调。 After digging around in the Android source code, I found out why that is: In the listen(PhoneStateListener listener, int events) method of the TelephonyManager the wrong subscriptionId is used, ie not the one set in the TelephonyManager but the one in the PhoneStateListener object, which is the subscriptionId of the first SIM card, by default: 在Android源代码周围挖掘后,我发现这是为什么:在listen(PhoneStateListener listener, int events)的方法TelephonyManager错误subscriptionId使用,即不能在一组TelephonyManager但一个在PhoneStateListener对象,默认为第一个SIM卡的subscriptionId:

public void listen(PhoneStateListener listener, int events) {
    if (mContext == null) return;
    try {
        Boolean notifyNow = (getITelephony() != null);
        sRegistry.listenForSubscriber(listener.mSubId, */ HERE: listener.mSubId is used instead of this.mSubId */
            getOpPackageName(), listener.callback, events, notifyNow);
    } catch (RemoteException ex) {
        // system process dead
    } catch (NullPointerException ex) {
        // system process dead
    }
}

This problem could be solved by setting the correct subscriptionId for the PhoneStateListener object, however the appropriate constructor is hidden: 可以通过为PhoneStateListener对象设置正确的subscriptionId来解决此问题,但是隐藏了适当的构造函数:

/**
 * Create a PhoneStateListener for the Phone using the specified subscription.
 * This class requires Looper.myLooper() not return null. To supply your
 * own non-null Looper use PhoneStateListener(int subId, Looper looper) below.
 * @hide */<-- HIDDEN, NOT ACCESSIBLE*/
 */
public PhoneStateListener(int subId) {
    this(subId, Looper.myLooper());
} 

I was able to "solve" this with reflection, by setting the mSubId field of the PhoneStateListener object to the appropriate subscriptionId of the second SIM card. 通过将PhoneStateListener对象的mSubId字段设置为第二张SIM卡的相应subscriptionId,我可以通过反射来“解决”此问题。

But there has to be a better way to do this, am I missing something? 但是必须有一种更好的方法来做到这一点,我是否错过了一些东西?

I make simple ArrayList with Listeners and it's work for me fine (it's Kotlin btw) 我用侦听器制作了简单的ArrayList,对我来说很好用(这是Kotlin btw)

In my activity: 在我的活动中:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.sim_selector)
    checkForForwarding()
}

fun getSimsCount(): Int {
    val subscriptionManager = SubscriptionManager.from(this)
    val activeSubscriptionInfoList = subscriptionManager.activeSubscriptionInfoList
    return activeSubscriptionInfoList.size
}

class SimForwardListeners{
    var subscriptionId: Int = 0
    lateinit var manager: TelephonyManager
    lateinit var phoneStateListener: MyPhoneStateListener
}

private val simsForwardListeners: ArrayList<SimForwardListeners> = arrayListOf()

fun checkForForwarding() {
    val subscriptionManager = getSystemService(TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager

    for (slotIndex in 0 until getSimsCount()) {
        val z = SimForwardListeners()
        z.phoneStateListener = MyPhoneStateListener(slotIndex)
        z.phoneStateListener.setView(this)
        z.subscriptionId = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(slotIndex).subscriptionId
        z.manager = (getSystemService(TELEPHONY_SERVICE) as TelephonyManager).createForSubscriptionId(z.subscriptionId)
        z.manager.listen(z.phoneStateListener, PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR)
        simsForwardListeners.add(z)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM