在Android中检测连接状态更改时的竞争条件

时间:2017-01-23 13:01:21

标签: android networking race-condition connectivity

我需要在Android应用中监控并确定连接状态的变化。为此,我已将我的班级注册为广播接收器:

Notice: Undefined variable: columns 
Notice: Undefined variable: columns 
Warning: implode(): Invalid arguments passed 

现在,要确定连接状态,您可以执行以下操作:

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

问题是ConnectivityManager.EXTRA_NETWORK_INFO已弃用。现在,建议您将@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.. } CONNECTIVITY_SERVICE一起使用,类似于:

getActiveNetworkInfo()

这提出了以下问题:

在第二个实现中,当使用 CONNECTIVITY_SERVICE 时,EXTRA_NETWORK_INFO:

是否有竞争条件的机会?由于@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.. } 是异步调用的,当从连接服务获取网络信息时,连接状态可能与意图中的网络信息不同(因为连接可能同时发生变化)? 这意味着,在使用意图时,我确信网络信息包含触发onReceive的数据,但在使用服务时 - 网络信息可能会有所不同......?

如果是,那么获取触发onReceive的信息的最佳方法是什么? 此外,如果这样做的唯一方法是继续使用意图 - 不是两个真相来源吗? (一个来自连接服务,一个来自发送的意图......)

更新

可能的竞争条件的一个例子:

有人连接到WiFi并立即断开与WiFi的连接。这将导致发送2个意图(一个用于连接到WiFi,另一个用于断开WiFi。实际发送更多意图,但我将重点关注这些2)。我要问的可能的竞争条件是:当我们获得第一个意图(WiFi连接)时,额外意图onReceive将导致EXTRA_NETWORK_INFOisConnected = true。但是,有可能当我从连接服务获取数据时,由于networkType = TYPE_WIFI被异步调用,WiFi已经断开连接,导致onReceiveisConnected = false,而意图仍然存在为networkType = TYPE_WIFI的此次调用保留正确的值?或者这总是足够快,以便您从onReceive中的连接服务中获得正确的值。?

1 个答案:

答案 0 :(得分:0)

我的解决方案是每次连接更改时发送广播,如果连接状态为up或down,则添加额外的内容,希望它有所帮助:

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>