Nougat 上未调用 TelephonyManager 的 PhoneStateListener

TelephonyManager's PhoneStateListener is not called on Nougat

我制作了一个示例应用程序和 PhoneStateListener

TelephonyManager telephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object
    telephony.listen(new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            Log.i("brian", "call state = " + state + " incoming number " + incomingNumber);
            switch (state) {
                case TelephonyManager.CALL_STATE_IDLE:
                    break;
                case TelephonyManager.CALL_STATE_RINGING:

                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:

                    break;
            }
        }
    }, PhoneStateListener.LISTEN_CALL_STATE); //Register our listener with TelephonyManager

    Log.i("brian", "READ_PHONE_STATE = " + ContextCompat.checkSelfPermission(this,
            Manifest.permission.READ_PHONE_STATE));

按预期工作,但是当我将以上代码添加到我的更大的应用程序时,onCallStateChanged 仅在最初订阅时调用。没有 phone 状态变化通知我。在这两个项目中,底部日志行 "READ_PHONE_STATE = " 始终被授予,我的目标是 sdk 22,所以我认为没有 运行time 权限。在我较大的应用程序中,我将代码粘贴到主要 activity 和长期服务中,两者都没有获得状态更改事件。当我 运行 我的代码在 android < 7.0 上时,它们都可以工作,我不知道为什么。在警告或错误日志中看不到任何实质内容。

尝试在服务的 onCreate 方法中注册您的侦听器。它适用于下面的 me.Find 示例代码:

    private TelephonyManager tm;

    @Override
    public void onCreate() {
        super.onCreate();

        //Set listener for TelephonyManager tm.
        tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        tm.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }


private PhoneStateListener phoneStateListener = new PhoneStateListener() {
    public void onCallStateChanged(int state, String incomingNumber) {

        if (state == TelephonyManager.CALL_STATE_RINGING) {
                    Log.i(LOG_TAG,"State : RING RING");

        }
        if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
                    Log.i(LOG_TAG,"State : OFFHOOK");
        }

        if (state == TelephonyManager.CALL_STATE_IDLE) {
                    Log.i(LOG_TAG,"State : IDLE");
        } 
    }
};

正如 Vairavan 在 回答中提到的,PhoneStateListener 的引用方式发生了内部变化:

Local reference to PhoneStateListener is kept track internally only by a weak reference. This makes it eligible for garbage collection upon function exit and once the listener is finalized, apps will not receive any further updates. Solution is to keep a reference to PhoneStateListener via class member variable.

参见:https://github.com/aosp-mirror/platform_frameworks_base/commit/f5d7c587e86c64e657a15a12ad70e75d47c48d99#diff-5af2ac899de823cf60597e554bf67fe0