开发者

roaming detection in android

I'm trying to detect when the roaming activation occurs. So far I've used the following piece of code, but because I haven't been able to test it I am unaware of it's correctness

TelephonyManager telephonyManager = TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); 

PhoneStateListener cellLocationListener = new PhoneStateListener() {
public void onCellLocationChanged(CellLocation location) {
  if(telephonyManager.isNetworkRoaming()
  {
    Toast.makeText(getApplicationContext(),"in roaming",Toast.LENGTH_LONG).show();
   }
 }
};

telephonyManager.listen(cellLocationListener, PhoneStateListener.LISTEN_CELL_LOCATION);

I've written thi开发者_开发知识库s , thinking that in order for roaming to activate first the signal cell must change. Please let me know whether my deduction is correct or not, and if not how could I accomplish this.


You can also test for isNetworkRoaming() in TelephonyManager if you want to know if there is Voice Roaming, even if the receiver is triggered by android.net.conn.CONNECTIVITY_CHANGE. I think this will also avoid the bug when the getActiveNetworkInfo() returns null.

public class RoamingListener extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        TelephonyManager telephony =
            (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (telephony.isNetworkRoaming())
            Toast.makeText(context, "Is on TelephonyM Roaming", Toast.LENGTH_LONG).show();
    }
}


I think you want to use isRoaming() in NetworkInfo class. But first you want to register a change broadcast listener:

<receiver android:name="YourListener">
  <intent-filter>
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

This gives you an action name: ConnectivityManager.CONNECTIVITY_ACTION

ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
//[edit: check for null]
if(ni != null) {
  //...Here check if this is connected and available...
  return ni.isRoaming();
}

[edit: known issue] NOTE: There seems to be a bug on certain versions, where getActiveNetworkInfo() returns null if roaming. See here: http://code.google.com/p/android/issues/detail?id=11866

I hope this helps!

Emmanuel


Reliable way of getting event when Roaming state changes is

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        PhoneStateListener phoneStateListener = new PhoneStateListener() {
            @Override
            public void onServiceStateChanged(ServiceState serviceState) {
                super.onServiceStateChanged(serviceState);
                if (telephonyManager.isNetworkRoaming()) {
                    // In Roaming
                } else {
                    // Not in Roaming
                }
                // You can also check roaming state using this
                if (serviceState.getRoaming()) {
                    // In Roaming
                } else {
                    // Not in Roaming
                }
            }
        };

Whenever the Roaming state is detected , PhoneListener will be notified using serviceStateChanged method.

I confirmed this by looking at the AOSP source code.

CDMA

https://android.googlesource.com/platform/frameworks/opt/telephony/+/master/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java

CDMA LTE

https://android.googlesource.com/platform/frameworks/opt/telephony/+/master/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java

GSM

https://android.googlesource.com/platform/frameworks/opt/telephony/+/master/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java

Check the method pollStateDone() , this is where the roaming state is set for the TelephonyManager


With Android 5.1 update, there is now a very easy roaming detection: just use the SubscriptionManager and get a roaming info from SubscriptionInfo getDataRoaming(). If there are multiple SIMs, only the info from active one is returned, which is convenient.


In my case I'm already listening for network state changes using the TelephonyManager and PhoneStateListener so, like the original questioner, I'm wondering whether roaming events can be detected there.

(This would be an alternative to using the ConnectivityManager/NetworkInfo solution in the accepted answer.)

To detect changes, the original question suggests listening for changes in cell location but I wonder if this wouldn't cause more events then necessary.

I would imagine that a change in the roaming state can only occur with a change in the network state.

protected PhoneStateListener psl = new PhoneStateListener() {
    public void onDataConnectionStateChanged(int state, int networkType) {
        if (TelephonyManager.DATA_CONNECTED == state)
            isRoaming = teleman.isNetworkRoaming();
                // teleman is an instance of TelephonyManager
    }
}

public static final int pslEvents = PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;

TelephonyManager teleman = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
teleman.listen( psl, pslEvents );

There are two caveats to this method, but I think that the ConnectivityManager solution (in the accepted answer) has the same issues:

  1. I'm listening for changes in DATA network state. If user doesn't establish a data connection (e.g. they are just voice roaming) then it won't work, but I don't think this is a problem because most of us are looking to detect data roaming (e.g. so our apps don't use data when the user is roaming).

  2. I'm not certain that there must be a change in data connection state when the user starts roaming - it is just my theory and I would be interested in hearing if anyone knows better.

Finally, let me add that it is possible that listening to PhoneStateListener::onServiceStateChanged() could be the best solution of all: simple and with the fewest unnecessary events (this should be triggered rarely) but I find the docs ambiguous and can't tell whether the PSL event gets triggered for a change in any of the ServiceState object's attributes (e.g. including roaming) or just for the ServiceState's service state attribute.


This works perfectly without any lisstener 1 for roaming and 0 for nonroaming

try {
            int roaming=    Settings.Secure.getInt(getContentResolver(), Settings.Secure.DATA_ROAMING);
            Log.e("roaming","roaming"+roaming);

        }
        catch (Exception e)
        {
            Log.e("Exception","Exception"+e.getLocalizedMessage());
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜