Android - 如何通过密码了解SSID失败?

时间:2017-04-26 12:57:08

标签: android android-wifi android-broadcastreceiver wifimanager android-wireless

我需要扫描未知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动作继续接收,但它并不意味着密码失败。

2 个答案:

答案 0 :(得分: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仅在ASSOCIATEDFOUR_WAY_HANDSHAKE出现一次时才有效,因此我将assoc变量设为安全防范。反映“无效密码”当然不是100%准确,但我没有其他更好的选择。

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

这就是我的所作所为:

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);
}

答案 1 :(得分:1)

添加BrocastReciver以执行操作“SUPPLICANT_STATE_CHANGED_ACTION” 然后在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);
    }
}