Состояние гонки при обнаружении изменения состояния подключения в Android

Мне нужно отслеживать и определять изменения состояния подключения в моем приложении для Android. Для этого я зарегистрировал свой класс в качестве широковещательного приемника:

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
context.registerReceiver(this, filter);

Теперь для определения статуса подключения вы можете сделать следующее:

@Override
public void onReceive(Context context, Intent intent) {
  if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
    return;
  }
  NetworkInfo aNetworkInfo =
      intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
  if (aNetworkInfo == null) {
    return;
  }

  boolean isConnected = aNetworkInfo.isConnected();
  int networkType = aNetworkInfo.getType();
  // by using isConnected & networkType, get the new connectivity status..
}

Проблема в том, что ConnectivityManager.EXTRA_NETWORK_INFO устарел. Теперь вам предлагается использовать CONNECTIVITY_SERVICE с getActiveNetworkInfo(), что-то вроде этого:

@Override
public void onReceive(Context context, Intent intent) {
  if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
    return;
  }
  ConnectivityManager connManager = 
      (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  if (connManager == null) {
    return;
  }
  NetworkInfo activeNetworkInfo = connManager.getActiveNetworkInfo();
  boolean isConnected =
      (activeNetworkInfo != null) && activeNetworkInfo.isConnected();
  int networkType =
      (activeNetworkInfo != null) ? activeNetworkInfo.getType() : -1;
  // by using isConnected & networkType, get the new connectivity status..
}

Это поднимает следующий вопрос:

Во второй реализации при использовании CONNECTIVITY_SERVICE и не EXTRA_NETWORK_INFO:

Есть ли шанс на состояние гонки? Поскольку onReceive вызывается асинхронно, при получении информации о сети от службы подключения может ли состояние подключения отличаться от информации о сети в намерении (поскольку подключение может измениться в это время)? Это означает, что при использовании намерения я уверен, что информация о сети включает данные, вызвавшие onReceive, но при использовании службы информация о сети может быть другой...?

Если да, то как лучше всего получить информацию, вызвавшую onReceive? Кроме того, если единственный способ сделать это - продолжать использовать намерение - разве это не два источника правды? (один из службы подключения и один из отправленного намерения...)

ОБНОВЛЕНИЕ:

Пример возможного состояния гонки:

Кто-то подключился к WiFi и тут же отключился от WiFi. Это приведет к отправке 2 намерений (одно для подключения к WiFi и одно для отключения от WiFi. На самом деле отправляется больше намерений, но я сосредоточусь на этих двух). Возможные условия гонки, о которых я спрашиваю, таковы: когда мы получаем первое намерение (подключение WiFi), дополнительное намерение EXTRA_NETWORK_INFO приведет к isConnected = true и networkType = TYPE_WIFI. Но возможно ли, что когда я получаю данные из службы подключения, поскольку onReceive вызывается асинхронно, WiFi уже отключается, что приводит к isConnected = false и networkType = TYPE_WIFI, в то время как намерение все еще содержит правильные значения для этого вызова onReceive? Или это всегда будет происходить достаточно быстро, поэтому вы получите правильные значения от службы подключения в onReceive.. ?


person Guy    schedule 23.01.2017    source источник


Ответы (1)


Мое решение заключалось в отправке широковещательной рассылки каждый раз при изменении соединения с добавлением дополнительного, если состояние соединения установлено или отключено, надеюсь, это поможет:

public class ConnectivityChangeReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    Log.i(context.getClass().getName(), " Changed connection ");
    context.sendBroadcast(new Intent(MyApplication.ACTION_CONNECTION_CHANGED)
            .putExtra(MyApplication.INTENT_EXTRA_CONNECTION_STATUS,NetWorkUtils.isNetworkAvailable(context)));
}}


public static boolean isNetworkAvailable(Context context) {
    ConnectivityManager cm =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null &&
            activeNetwork.isConnectedOrConnecting();
}

Манифест Android:

<receiver android:name=".ConnectivityChangeReceiver">
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
    </receiver>
person AmirG    schedule 23.01.2017
comment
Итак, еще раз - вы используете службу подключения, а не информацию в отправленном намерении -> поэтому остается вопрос (информация от службы всегда будет такой же, как информация в намерении, или состояние гонки может вызвать эту информацию отличаться ?) - person Guy; 23.01.2017
comment
хорошо, согласно документации, вы можете использовать дополнительные сведения о состоянии сети, но я выбрал прямое решение, чтобы проверять каждый раз при получении, чтобы быть уверенным. - person AmirG; 23.01.2017
comment
проверьте developer.android.com/reference/android/net/ по адресу CONNECTIVITY_ACTION - person AmirG; 23.01.2017
comment
Да, я видел документацию, но опять же, дополнительный EXTRA_NETWORK_INFO устарел -> предлагает вам использовать службу подключения. Но тогда остается мой вопрос: возможно ли состояние гонки? Могут ли данные, которые мы получаем от службы подключения в onReceive, отличаться от данных в дополнительных намерениях, поскольку onReceive вызывается асинхронно? - person Guy; 23.01.2017