How to get a PhoneStateListener when using Dual SIM functionality

故事扮演 提交于 2019-12-09 18:45:51

问题


so I am currently implementing a call forwarding feature in Android, for dual SIM devices. In order to read the current state of the call forwarding (enabled/disabled) for a SIM card, I do the following:

  1. I create a TelephonyManager object:

val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager

  1. I create a PhoneStateListener object and override the onCallForwardingIndicatorChanged method:

    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:

telephonyManager.listen(myPhoneStateListener, LISTEN_CALL_FORWARDING_INDICATOR)

This works perfectly fine for the primary (the first) SIM card.

But I am having trouble doing the same for the second SIM card. Here is how I am trying to do it:

  1. I use a SubscriptionManager object to retrieve the subscriptionId of the second SIM card:

    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:

    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:

    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. 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, i.e. 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:

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:

/**
 * 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.

But there has to be a better way to do this, am I missing something?


回答1:


I make simple ArrayList with Listeners and it's work for me fine (it's 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)
    }
}


来源:https://stackoverflow.com/questions/47352840/how-to-get-a-phonestatelistener-when-using-dual-sim-functionality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!