androidmultithreadingandroid-servicerunnableandroid-thread

Calling PhoneStateListener in a thread inside a service


I'm developing a music app that uses a service to play the songs in the background. Inside my service I have a code for listening the phone state and pausing the music if a call comes in and then playing it again after the call finishes.

This code works fine inside onCreate but when I put it inside a Thread it gives: java.lang.NullPointerException: Attempt to read from field 'android.os.MessageQueue android.os.Looper.mQueue' on a null object reference

What I tried: I tried to put a Looper.prepare inside the code. This prevented it from crashing but when a phone call comes, the song doesn't stop. I guess I didn't use Looper function right.

final class phoneStateThread implements Runnable
    {

        @Override
        public void run() {


                Log.v(TAG,"Starting telephony");
                telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
                Log.v(TAG,"Starting listener");
                phoneStateListener = new PhoneStateListener(){
                    @Override
                    public void onCallStateChanged(int state, String incomingNumber) {
                        Log.v(TAG,"Starting CallStateChange");
                        switch (state){

                            //=====Phone ringing. Pause music=====
                            case TelephonyManager.CALL_STATE_OFFHOOK:
                            case TelephonyManager.CALL_STATE_RINGING:
                                if(mediaPlayer!=null) {
                                    pauseMedia();
                                    isPausedInCall=true;
                                }

                                break;

                            //=====Phone idle. start music=====
                            case TelephonyManager.CALL_STATE_IDLE:
                                if(mediaPlayer!=null){
                                    if(isPausedInCall){
                                        isPausedInCall=false;
                                        playMedia();
                                    }
                                }
                                break;
                        }

                    }

                };


                telephonyManager.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);
            }
        }

Solution

  • This code works fine inside onCreate

    Because it using Looper of Android Main Thread, when you put your code into Thread, Looper not available there, you need make your own Looper. Try this

    final class phoneStateThread implements Runnable
        {
    
            @Override
            public void run() {
    
                    Looper.prepare()
                    Log.v(TAG,"Starting telephony");
                    telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
                    Log.v(TAG,"Starting listener");
                    phoneStateListener = new PhoneStateListener(){
                        @Override
                        public void onCallStateChanged(int state, String incomingNumber) {
                            Log.v(TAG,"Starting CallStateChange");
                            switch (state){
    
                                //=====Phone ringing. Pause music=====
                                case TelephonyManager.CALL_STATE_OFFHOOK:
                                case TelephonyManager.CALL_STATE_RINGING:
                                    if(mediaPlayer!=null) {
                                        pauseMedia();
                                        isPausedInCall=true;
                                    }
    
                                    break;
    
                                //=====Phone idle. start music=====
                                case TelephonyManager.CALL_STATE_IDLE:
                                    if(mediaPlayer!=null){
                                        if(isPausedInCall){
                                            isPausedInCall=false;
                                            playMedia();
                                        }
                                    }
                                    break;
                            }
    
                        }
    
                    };
    
    
                    telephonyManager.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);
                    Looper.loop()
                }
            }