NullPointerExecption when calling a PhoneStateListener in a service
Asked Answered
F

1

12

I've got a PhoneStateLister where I get a bunch of data and I send to a server.

If I call the listener in a fragment, it's all good, but when I'm calling it in a service, I get a NullPointerException.Here is my code:

PhoneStateListener:

public class CarrierStateListener extends PhoneStateListener {

private Context context;
private TelephonyManager telephonyManager;
private String carrierName;
private int mSignalStrength = 0;
private int mCellTowerID = 0;
private int mCellTowerAreCode = 0;
private int mcc = 0;
private int mnc = 0;


public CarrierStateListener(Context context) {
    this.context = context;
}

/**
 * Get the Signal strength from the provider, each time there is an update
 */
@Override
public void onSignalStrengthsChanged(final SignalStrength signalStrength) {
    super.onSignalStrengthsChanged(signalStrength);

    telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    GsmCellLocation loc = (GsmCellLocation) telephonyManager.getCellLocation();
    String networkOperator = telephonyManager.getNetworkOperator();

    /** Retrieving the carrier name **/
    carrierName = telephonyManager.getNetworkOperatorName();
    UserInformation.getSingleton(context).setNetwork(carrierName);

    /** Retrieving the RSSI value **/
    mSignalStrength = signalStrength.getGsmSignalStrength();
    mSignalStrength = (2 * mSignalStrength) - 113; // -> dBm
    UserInformation.getSingleton(context).setRssi(String.valueOf(mSignalStrength));

    /** Retrieve the cell tower id (CID) and the LAC (location area code) **/
    mCellTowerID = loc.getCid();
    mCellTowerAreCode = loc.getLac();
    UserInformation.getSingleton(context).setCellId(String.valueOf(loc.getCid()));

    /**tower mobile network code (mnc) and mobile country code (mcc) **/
    if (networkOperator != null) {
        mcc = Integer.parseInt(networkOperator.substring(0, 3));
        mnc = Integer.parseInt(networkOperator.substring(3));
        UserInformation.getSingleton(context).setMnc(String.valueOf(mnc));
        UserInformation.getSingleton(context).setMcc(String.valueOf(mcc));

    } else {
        Toast.makeText(context, "Couldn't retrieve mnc and mcc because network operator is "
                + networkOperator, Toast.LENGTH_SHORT).show();
    }


}

and My Service:

public class SendDataService extends Service {

private static final String TAG = "SendDataService";
private Thread t;
private TelephonyManager telephonyManager;
private CarrierStateListener pslistener;

@Override
public IBinder onBind(Intent intent) {
    return null;
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SendDataService");
    wl.acquire();

    t = new Thread() {
        @Override
        public void run() {
            while (true) {
                try {

                    Log.e(TAG, "sending data...");

                    //post request to send data
                    Thread.sleep(6000);

                } catch (InterruptedException ie) {
                }
            }
        }
    };
    t.start();

    Log.e(TAG, "the SendDataService started");
    return START_STICKY;
}

and I start the Service in onResume() of a fragment:

getActivity().startService(new Intent(getActivity(), SendDataService.class));

when the fragment starts...this is the EXCEPTION I get:

09-14 16:11:05.034  21697-21697/? E/CallDataService﹕ the SendDataService started
09-14 16:11:05.036  21697-21729/? E/CallDataService﹕ sending data...
09-14 16:11:05.037  21697-21729/? E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-2445
    Process: xxxxxxxx, PID: 21697
    java.lang.NullPointerException: Attempt to read from field 

'android.os.MessageQueue android.os.Looper.mQueue' on a null object reference
            at android.os.Handler.<init>(Handler.java:229)
            at android.os.Handler.<init>(Handler.java:137)
            at android.telephony.PhoneStateListener$1.<init>(PhoneStateListener.java:270)
            at android.telephony.PhoneStateListener.<init>(PhoneStateListener.java:270)
            at android.telephony.PhoneStateListener.<init>(PhoneStateListener.java:240)
            at xxxxxxxxxxxxx.CarierStateListener.<init>(CarierStateListener.java:27)
            at xxxxxxxxx.SendDataService.listenForEvents(SendDataService.java:96)
            at xxxxxx.util.SendDataService.access$000(SendDataService.java:25)
            at xxxxxxxxxx.util.SendDataService$1.run(SendDataService.java:53)
Foamflower answered 14/9, 2015 at 15:16 Comment(6)
show SendDataService class codeUnguentum
it's displayed under "My service"Foamflower
Where is listenForEvents method? please showUnguentum
telephonyManager = (TelephonyManager) SendDataService.this.getSystemService(Context.TELEPHONY_SERVICE); pslistener = new CarrierStateListener(SendDataService.this); telephonyManager.listen(pslistener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);Foamflower
As in log it's show problem is at line number 96 in listenForEvents method of SendDataService classUnguentum
Did answer from Kvant help you? If so, please mark it, if not, could you provide your own answer to the problem?Thurlow
A
18

This is a message queue problem you have to initialize the looper before calling telephonyManager.listen and loop afterwards.

 new Thread(new Runnable() {
                    @Override
                    public void run() {
                        quitLooper = false;
                        Looper.prepare();
                        tManager.listen(new PhoneStateListener() {
                            @Override
                            public void onSignalStrengthsChanged(SignalStrength signalStrength) {
                                super.onSignalStrengthsChanged(signalStrength);
                                lastSignalStrength = signalStrength;
                                if(quitLooper)
                                    Looper.myLooper().quit();

                            }
                        }, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);

                        Looper.loop();
                    }
                }).start();
Acquire answered 31/12, 2015 at 14:42 Comment(3)
Where do you set quitLooper? When doing it from "outside", perhaps it would be a reasonable approach to check for Thread.currentThread().isInterrupted() instead and stop the processing with howYouCallTheThread.interrupt()?Djerba
Does a new thread have to be created? Or, is it safe to just call Looper.prepare()?Bevatron
@Bevatron If the listen method called from main thread there is no need for looper initialization at all.Acquire

© 2022 - 2024 — McMap. All rights reserved.