2

I am trying to make my broadcast receiver fire when the phone goes in and out of reception areas. The issue is the receiver never gets called when the cell reception changes. The BroadcastReceiver works fine for getting phone call states (call idle, started ect...), and also for getting the airplane mode switched on and off because the broadcast receiver handles both.

I added the permissions and intent filter to the receiver in the manifest and they are working fine.

Here is what I have for my BroadcastReceiver and PhoneStateListener.

public class PhoneStateReceiver extends BroadcastReceiver {

private PhoneStateListener mListener = new ServiceStateListener();
private TelephonyManager mTelephonyManager;
private Context mContext;
/**
 * TODO add some sort of call back interface to allow for different uses of this phone state receiver
 */

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    mContext = context;
    if (action.intern().equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
        boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
        if (!isAirplaneModeOn) {
            SmsRetryManager.getInstance().retryAllSms(context);
        }
    } else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
        mTelephonyManager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        Toast.makeText(mContext, "Receiver registered!", Toast.LENGTH_LONG).show();
        mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_SERVICE_STATE);
        mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
    }
}


public void onDestroy() {
    mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
}

private class ServiceStateListener extends PhoneStateListener {

    @Override
    public void onServiceStateChanged (ServiceState serviceState) {
        super.onServiceStateChanged(serviceState);
        boolean connected = (serviceState.getState() == ServiceState.STATE_IN_SERVICE);
        if (connected) {
            Toast.makeText(mContext, "Connection Gained!", Toast.LENGTH_LONG).show();
            //todo retry sms here
            SmsRetryManager.getInstance().retryAllSms(mContext);

        } else {
            Toast.makeText(mContext, "Connection Lost!", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onSignalStrengthsChanged(SignalStrength signalStrength) {
        super.onSignalStrengthsChanged(signalStrength);
        Toast.makeText(mContext, "Signal changed - cdma : " + signalStrength.getCdmaDbm() + " gsm : " + signalStrength.getGsmSignalStrength(), Toast.LENGTH_LONG).show();
    }
}

Any insight would be awesome. I have been banging my head on this one for a while.

Thanks!

ocross
  • 593
  • 1
  • 5
  • 24

1 Answers1

2

I assume you are listening the broadcast android.intent.action.SERVICE_STATE

If so, try using:

if (TelephonyManager.getnetworkOperator.length()==0) connected=false;

on your OnReceive method, to know if the phone is not connected. It works fine for me.

If this solution doesn't work, please show how you register the receiver: is it statically registered at manifest.xml? or dynamically with PackageManager.setComponentEnabledSetting? Note: With static registration you'll find the receiver is not triggered after reinstalling the app, needing to add to the receiver tag

<intent-filter> <action android:name= "android.intent.action.MY_PACKAGE_REPLACED"/></intent-filter>

You can also look at the values that return the ServiceState. See here http://developer.android.com/reference/android/telephony/ServiceState.html

And check which of these values is returned:

int STATE_EMERGENCY_ONLY = The phone is registered and locked. Only emergency numbers are allowed.

int STATE_IN_SERVICE = Normal operation condition, the phone is registered with an operator either in home network or in roaming.

int STATE_OUT_OF_SERVICE = Phone is not registered with any operator, the phone can be currently searching a new operator to register to, or not searching to registration at all, or registration is denied, or radio signal is not available.

int STATE_POWER_OFF = Radio of telephony is explicitly powered off.

Joanmi Bardera
  • 351
  • 1
  • 7
  • So the service_state does seem to be correct in terms of getting the broadcast receiver to call on service change, but could you explain the networkOperator length check? That seems like a hacky way to accomplish this. I would assume the intent comes with some parameters that will allow you to tell if you went in or out of service. Unfortunately googles documents give no insight. – ocross Aug 18 '15 at 16:41
  • Well, as explained here http://developer.android.com/reference/android/telephony/TelephonyManager.html#getNetworkOperator%28%29 it returns the numeric name (MCC+MNC) of current registered operator. So, if there is no registered operator (like in case out of reception) then this value will be empty. – Joanmi Bardera Aug 18 '15 at 17:17
  • But yes, you can also check the values that return the ServiceState. See here http://developer.android.com/reference/android/telephony/ServiceState.html – Joanmi Bardera Aug 18 '15 at 17:25
  • You can check which of these values is returned: `int STATE_EMERGENCY_ONLY = The phone is registered and locked. Only emergency numbers are allowed.` `int STATE_IN_SERVICE = Normal operation condition, the phone is registered with an operator either in home network or in roaming.` `int STATE_OUT_OF_SERVICE = Phone is not registered with any operator, the phone can be currently searching a new operator to register to, or not searching to registration at all, or registration is denied, or radio signal is not available.` `int STATE_POWER_OFF = Radio of telephony is explicitly powered off.` – Joanmi Bardera Aug 18 '15 at 17:26
  • Thats more of what I was looking for. Any idea if there is a way to get signal strength from the intent or from something without adding a PhoneStateListener? Also edit your answer to include the intent names. For Jellybean MR2 and up its "voiceRegState" and "dataRegState", for apis bellow that just check "state". – ocross Aug 20 '15 at 01:04
  • Hi ocross. I don't know, sorry. As you pointed, the usual way to get signal strength is using a listener, well explained here http://stackoverflow.com/questions/1967136/how-to-get-cell-service-signal-strength-in-android BUT I've found that answer http://stackoverflow.com/questions/17618167/get-signalstrength-without-using-phonestatelistener-onsignalstrengthchanged that may help you (works only on API17). – Joanmi Bardera Aug 20 '15 at 01:21