检查 Wifi 连接时广播接收器未捕获所需的情况

Broadcast receiver doesn't catch required case when checking for Wifi connections

我正在构建一个应用程序,它有两个部分。在第一部分,用户扫描附近的主机点并获取可用网络列表。这部分工作正常。 第二部分,是有问题的部分。在这部分,用户选择要连接的网络,屏幕会相应更新。我实现了一个广播接收器来捕捉用户连接到所选网络的时间。当移动数据关闭时,广播接收器捕捉到正确的情况并且一切正常。但是,如果移动数据打开,广播接收器在连接到 wifi 时不会捕捉到这种情况,尽管我可以看到 phone 已经连接到 wifi。

这是我的广播接收器代码片段:

mConnectivityReceiver = new BroadcastReceiver() {
       @Override
       public void onReceive(Context context, Intent intent) {

           new Thread(new Runnable() {
               @Override
               public void run() {

                        final ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
                        final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

                        if(networkInfo != null && networkInfo.isAvailable()){

                            Log.e("connectivityReceiver", "networkInfo type " + networkInfo.getTypeName());
                           switch (networkInfo.getType()){

                               case ConnectivityManager.TYPE_WIFI://When mobile data is on, I never reach this case
                                   updateUI(networkInfo);
                                   break;
                               case ConnectivityManager.TYPE_MOBILE:
                                   //do nothing.
                                   break;
                           }

                        }
                    }

               public void updateUI(final NetworkInfo networkInfo){

                   if(networkInfo.isAvailable() && networkInfo.getExtraInfo()!= null){

                            Log.e("connectivityReceiver","networkInfo extra: " + networkInfo.getExtraInfo());

                            if(networkInfo.getExtraInfo() != null){

                                if(networkInfo.getExtraInfo().contains(selectedNetwork)) {
                                    networks.clear();
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            mAdapter.notifyDataSetChanged();
                                            mDiscoverNetworksBtn.setEnabled(true);
                                            mDiscoverNetworksBtn.setVisibility(View.VISIBLE);
                                            mProgressbar.setVisibility(View.GONE);
                                            mWaitMessage.setVisibility(View.GONE);

                                        }
                                    });

                                    unregisterReceiver(mConnectivityReceiver);
                                }
                                else if(!networkInfo.getExtraInfo().equals("<unknown ssid>")){
                                    Log.e("connectivityReceiver", "Error occurred while trying to connect to " + selectedNetwork);
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            Toast.makeText(IoTSetupActivity.this, "Error occurred while trying to connect to " + selectedNetwork, Toast.LENGTH_LONG).show();
                                            mProgressbar.setVisibility(View.GONE);
                                            mWaitMessage.setVisibility(View.GONE);
                                            mListview.setVisibility(View.VISIBLE);
                                        }
                                    });
                                }

                            }

                        }

                    }
                }).start();
            }
        };

这是我用来连接到所选网络的代码片段:

private void connectToNetwork(final Network network){

        final WifiConfiguration conf = new WifiConfiguration();
        conf.SSID = "\"" + network.getNetworkName() + "\"";
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);

            WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            wifiManager.addNetwork(conf);

            List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
            for(WifiConfiguration i : list){
                if(i.SSID != null && i.SSID.equals(conf.SSID)){

                    registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

                    Log.e("connectToNetwork", "Disconnecting from " + wifiManager.getConnectionInfo().getSSID());
                    boolean isDisconnected = wifiManager.disconnect();
                    Log.v("connectToNetwork", "isDisconnected: " + isDisconnected);

                    boolean isEnabled = wifiManager.enableNetwork(i.networkId, true);
                    Log.v("connectToNetwork", "isEnabled: " + isEnabled);

                    Log.e("connectToNetwork", "Trying to reconnect to " + conf.SSID);
                    boolean isReconnected = wifiManager.reconnect();
                    Log.v("connectToNetwork", "isReconnected: " + isReconnected);

//                    Toast.makeText(IoTSetupActivity.this,"Connected to " + conf.SSID, Toast.LENGTH_LONG).show();
                    break;
                }
            }
}

根据 Denis 的回答编辑

public class ConnectivityNetworkCallback extends ConnectivityManager.NetworkCallback{

        @Override
        public void onAvailable(android.net.Network network) {
            super.onAvailable(network);

            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
                mConnectivityManager.bindProcessToNetwork(network);
            else
                ConnectivityManager.setProcessDefaultNetwork(network);

            NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
            int connectionType = networkInfo.getType();
            Log.e("networkCallback", "connectionType: " + networkInfo.getTypeName());
            switch(connectionType){

                case ConnectivityManager.TYPE_WIFI:
                    String networkName = networkInfo.getExtraInfo();

                    Log.e("networkCallback","network type wifi, extra: " + networkName);
                    break;
                case ConnectivityManager.TYPE_MOBILE:
                    Log.e("networkCallback","network type mobile, extra:  " + networkInfo.getExtraInfo());
                    break;
            }
        }

现在我的问题是,当我同时打开移动数据和 Wifi 并在 wifi 网络之间切换时,有时第一个日志会打印我已连接到移动设备,并且当设备连接到新设备时不会再次触发wifi,有时它会打印出我已连接到新的 wifi。

首先,当您调用 enableNetwork(id, true) 时,不需要 wifiManager.reconnect(),因为它已经尝试连接。

其次,您必须确保您之前没有通过系统设置手动连接到该网络。在这种情况下,您的应用不会连接到它,因为它是不允许的。如果您手动创建了连接,则必须先忘记该网络,以允许该应用程序重新创建该连接。之后,您会在系统设置中看到一个小文本提示是哪个应用创建了该配置。

第三,广播接收器不适合您的尝试。它有太多容易出错的情况。如果您正在处理 Android 5 及更高版本,请使用 ConnectivityManager.NetworkCallback 并监听 onAvailable() 调用。这将确保 wifi 连接已实际设置并可用。