3

I have made a sample app and the 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));

Works as expected, but when I add the above code to my much larger application the onCallStateChanged is only called when it is subscribed initially. No phone state changes are notified to me. On both projects the bottom log line "READ_PHONE_STATE = " was always granted and I'm targeting sdk 22 so no runtime permissions I think. In my larger app I have the code pasted in both the main activity and a long standing service, neither get state change events. They both work when I run my code on an android < 7.0 and I have no idea why. Don't see anything substantial in the warning or error logs.

L7ColWinters
  • 1,342
  • 1
  • 14
  • 31
  • Did you make any progress with this? I'm actually having a similar issue. In the emulator for 7.1 this works as expected, but I have users reporting what amounts to the listener not being called on their Pixel devices. I'll post if I make any headway. – Pinsickle Nov 21 '16 at 21:43
  • 1
    @Pinsickle what I ended up doing was just using the broadcast receiver approach instead of registering the listener. – L7ColWinters Nov 22 '16 at 23:11
  • I have a similar problem. My targetSdkVersion 26, and I request all permissions. I want to wrap a listener to Observable (RxJava). Full test here https://github.com/tim4dev/dirty_code/tree/master/Rx-Listener-to-Observable On Android 4.2 worked fine. On Android 8.0 called 2--3 times and dead. Steps to reproduce: run app on Android 8 (on real device or emulator), call, press disconnect (off hook), if you do it fast enough - everything will be ok, if you listen to short beeps and wait, the Listener dies and does not react any more. I avoided the problem by simple pooling (RxJava). – tim4dev Sep 25 '17 at 09:00
  • Normal (native) phone listener works well. Code by the link above. You can try go to API 26 with permission requests. – tim4dev Sep 25 '17 at 09:04
  • This worked for me (minSdkVersion 24): https://stackoverflow.com/questions/42213250/android-nougat-phonestatelistener-is-not-triggered You have to register the `TelephonyManager` to listen inside the `onStartCommand` method of the service instead of the `onCreate` method. – Eduardo Casas Oct 07 '17 at 06:00

2 Answers2

4

As Vairavan mentioned in this answer, there was an internal change in how the PhoneStateListener is referenced:

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.

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

TheIT
  • 11,919
  • 4
  • 64
  • 56
3

Try registering your listener in onCreate method of your service. It's works for me.Find example code below :

    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");
        } 
    }
};