0

我需要扫描未知 SSID 列表并使用一些预定义的密码登录该接入点。如果成功,则继续下一个任务。如果失败,则尝试登录下一个 SSID。

我尝试尽可能多地注册,看看哪个有效:

receiverWifi = new WifiReceiver();
registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
registerReceiver(receiverWifi, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
registerReceiver(receiverWifi, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
registerReceiver(receiverWifi, new IntentFilter(WifiManager.NETWORK_IDS_CHANGED_ACTION));
registerReceiver(receiverWifi, new IntentFilter(WifiManager.ACTION_PICK_WIFI_NETWORK));
registerReceiver(receiverWifi, new IntentFilter(WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE));
registerReceiver(receiverWifi, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
registerReceiver(receiverWifi, new IntentFilter(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION));

我用这样的密码连接 ssid:

WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = String.format("\"%s\"", ssid);
wifiConfig.preSharedKey = String.format("\"%s\"", password);
netId = mainWifi.addNetwork(wifiConfig);
if (netId != -1) {
    if (mainWifi.disconnect())
        if (mainWifi.enableNetwork(netId, true))
            if (mainWifi.reconnect()) {
            }
}

它确实流向了连接:

class WifiReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if  (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {

        } else if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {

            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();

            if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
                    networkInfo.isConnected()) {
                WifiInfo wifiInfo = mainWifi.getConnectionInfo();
                ssid = wifiInfo.getSSID();
                //able to know Wifi connected to ssid here
            }

            } else if (intent.getAction().equalsIgnoreCase(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
        }
    }
}

但是如何确定密码是否使用此 SSID 失败?我想知道密码是否失败,然后代码将尝试下一个 SSID。但是我应该使用哪个操作来知道密码尝试失败?目前我注意到只有android.net.wifi.STATE_CHANGE动作不断接收,但这并不意味着密码失败。

4

2 回答 2

2

WifiManager.ERROR_AUTHENTICATING并不总是出现,所以我最终得到了这个:

class WifiReceiverResult extends BroadcastReceiver {

    boolean assoc = false;

    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getAction().equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {

            SupplicantState supl_state = ((SupplicantState)intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
            switch (supl_state) {
                case ASSOCIATED:
                    assoc = true;
                    break;
                case FOUR_WAY_HANDSHAKE: //need this because ASSOCIATED sometimes skipped
                    assoc = true;
                    break;
                case DISCONNECTED:
                    if (assoc) {
                        assoc = false;
                        //... try next SSID
                    }
                    break;

        ...

由于DISCONNECTED仅当ASSOCIATEDORFOUR_WAY_HANDSHAKE出现一次时才有效,所以我将assoc变量作为安全防护。反映“无效密码”当然不是 100% 准确,但我没有其他更好的选择。

[更新]请记住,以上不是最终代码,您还应该处理 DISCONNECTED 的超时和最大尝试次数,否则可能只有几分钟后才能成功(这在我的要求中是不可接受的,我最好尝试下一个 SSID 然后重试SSID 的完整列表)或无限重复阶段 SCANNING...DISCONNECTED。

这就是我所做的:

Handler myHandler = new Handler(Looper.getMainLooper());
Runnable runner = new Runnable() {
    @Override
    public void run() {
        if (isTimeout) {

            //Network idle timeout 15 seconds, do scanning next again
            List<WifiConfiguration> list = mainWifi.getConfiguredNetworks(); //here might hang for 20 seconds !
            for( WifiConfiguration i : list ) {
                mainWifi.removeNetwork(i.networkId);
                mainWifi.saveConfiguration();
            }
            connectAPWithTimeout();
        }
    }
};
...
void connectAPWithTimeout() {
    if (runner != null) {
        myHandler.removeCallbacks(runner);
    }
    myHandler.postDelayed(runner, 15000);
    isTimeout = true;
    try {
        receiverWifiR.connectToAP(); //my custom method to connect to next ssid hotspot
    } catch (NullPointerException e) {
    }
}
...
class WifiReceiverResult extends BroadcastReceiver {
int attempt = 0;
...
@Override
public void onReceive(Context context, Intent intent) {
...
                    case DISCONNECTED:
                        attempt+=1;
                        if (assoc || attempt > 2) {
                            isTimeout = false;
                            assoc = false;
                            attempt = 0;
                            connectAPWithTimeout();
                        }
                        break;

并且不要忘记在重试课程或退出课程前连接时删除回调:

isTimeout = false;
if (runner != null) {
    myHandler.removeCallbacks(runner);
}
于 2017-04-26T19:27:56.043 回答
1

为动作“SUPPLICANT_STATE_CHANGED_ACTION”添加 BrocastReciver,然后在 onRecive 中添加波纹管代码

if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
    int linkWifiResult = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 123);
    if (linkWifiResult == WifiManager.ERROR_AUTHENTICATING) {
        Log.i(TAG,"pwd error);
    }
}
于 2017-04-26T15:29:46.427 回答