在Android中以编程方式连接到Wifi无法在Android M

时间:2018-04-18 20:02:24

标签: android android-wifi

我正在尝试创建一个应用程序将连接到Wi-Fi的应用程序。 它在Android 6下面的所有Android设备中连接到Wifi。但是在Android 6中,它会在10-20秒之后连接并丢弃。以下是完整的Wifi Manager代码。

我在下面的代码中做错了什么。 我要求运行时LOCATION权限,并要求打开位置。所有清单权限都在Manifest中添加。 ACCESS_WIFI_STATE,CHANGE_WIFI_STATE,CHANGE_NETWORK_STATE,ACCESS_NETWORK_STATE, ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION。

public class WifiManager implements Handler.Callback {

    private static final String TAG = WifiManager.class.getSimpleName();
    private Handler handler;
    private Context reactContext;

    private static final String WIFI_EVENT_NAME = "WiFiStatusEvent";
    private static final String WIFI_STATUS = "WiFiStatus";
    private static final int STATE_UNKNOWN = 0;
    private static final int STATE_WIFI_OFF = 1;
    private static final int STATE_WIFI_ON = 2;
    private static final int STATE_SSID_VISIBLE = 3;
    private static final int STATE_SSID_CONFIGURED = 4;
    private static final int STATE_SSID_ASSOCIATING = 5;
    private static final int STATE_SSID_ASSOCIATED = 6;
    // A slight delay after the wifi says it is connected before we return to the calling app.
    // (Sometimes the wifi isn't quite ready yet, even though it says it is)
    private static final long DELAY_AFTER_CONNECTION_TIMEOUT = 1000 * 2;
    // ESSID connect default timeout
    private static final long DEFAULT_TARGET_NETWORK_CONNECT_TIMEOUT = 15 * 1000;

    // Internal connection progress states
    private int state = STATE_UNKNOWN;
    // The system wifi manager
    private android.net.wifi.WifiManager wifi;
    // The application context to use for system functions
    private String targetSSID = null;
    // The given callback to message when we are done
    private Handler timeoutHandler = null;
    private static long timeout = 500000;

    public WifiManager(Context reactContext) {
        this.reactContext = reactContext;
        wifi = (android.net.wifi.WifiManager) reactContext.getApplicationContext().getSystemService(WIFI_SERVICE);
    }

    public void connectToHost(Context context, String host, String password) {
        WifiConfiguration wc = new WifiConfiguration();

        wc.SSID = host;
        //wc.preSharedKey = password;

        int netId = wifi.addNetwork(wc);

        try {
            wifi.enableNetwork(netId, true);
            wifi.setWifiEnabled(true);

            System.out.println("enabled network");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }


    public void connectToHost2(Context context, String host, String password) {
        WifiConfiguration wc = new WifiConfiguration();

        wc.SSID = host;
        //wc.preSharedKey = password;
        wc.status = WifiConfiguration.Status.ENABLED;
        wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA); // For WPA
        wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
        wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
        wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);


        int netId = wifi.addNetwork(wc);
        WifiConfiguration wifiConfig = setWifiConfiguration(targetSSID, WifiConfiguration.KeyMgmt.NONE);

        int networkId = wifi.addNetwork(wifiConfig);
        logInfo(TAG, "networkId :: " + networkId);

        wifi.saveConfiguration();


        try {
            wifi.enableNetwork(netId, true);
            wifi.setWifiEnabled(true);

            System.out.println("enabled network");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }

    public void connectToWifi() {

        try {
            WifiConfiguration wc = new WifiConfiguration();
            WifiInfo wifiInfo = wifi.getConnectionInfo();
            wc.SSID = "\"WIFI_SSID\"";
            wc.priority = 1;
            //wc.preSharedKey = "\"PASSWORD\"";
            wc.status = WifiConfiguration.Status.ENABLED;
            wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            int netId = wifi.addNetwork(wc);
            if (netId == -1) {
                netId = getExistingNetworkId(wc.SSID);
            }
            wifi.disconnect();
            wifi.enableNetwork(netId, true);
            wifi.reconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private int getExistingNetworkId(String SSID) {
        List<WifiConfiguration> configuredNetworks = wifi.getConfiguredNetworks();
        if (configuredNetworks != null) {
            for (WifiConfiguration existingConfig : configuredNetworks) {
                if (existingConfig.SSID.equals(SSID)) {
                    return existingConfig.networkId;
                }
            }
        }
        return -1;
    }

    public void connectToWifi(String wifiSSID) {


        logInfo(TAG, "Connecting to " + wifiSSID);

        if (null == handler) {
            handler = new Handler(this);
        }

        if (null == wifiSSID || wifiSSID.isEmpty()) {
            return;
        }

        displayLocationSettingsRequest(reactContext);

        this.targetSSID = wifiSSID;

        //removeNetwork();
        connectToTargetNetwork();


    }

    //@ReactMethod
    public void isConnected(String wifiSSID) {
        this.targetSSID = wifiSSID;

    }

    @Override
    public boolean handleMessage(Message msg) {

        if (null == msg) {
            logError(TAG, "Callback, error");
            return false;
        }

        if (null == msg.obj) {
            logError(TAG, "Callback, error");
            return false;
        }

        WifiStatus wifiStatus = (WifiStatus) msg.obj;
        if (null != wifiStatus) {
            logInfo(TAG, "ID :: " + wifiStatus.getId());
        }
        return false;
    }

    /**
     * WIFI state callback - Listening for WIFI on/off transitions
     */
    private BroadcastReceiver wifiStateReceiver = new BroadcastReceiver() {
        public void onReceive(Context c, Intent intent) {

            logInfo(TAG, "WifiStateReceiver - onReceive" + intent.getPackage());

            ConnectivityManager cm = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo currentNetworkInfo = cm.getActiveNetworkInfo();

            if (currentNetworkInfo != null && "WIFI".equals(currentNetworkInfo.getTypeName())) {

                logInfo(TAG, "NetworkInfo - TypeName = " + currentNetworkInfo.getTypeName() + ", state = " + currentNetworkInfo.getState());

                if (currentNetworkInfo.getState() == NetworkInfo.State.CONNECTED) {

                    if (isConnectedToTargetNetwork()) {
                        sendCallbackMessage(handler, WifiStatus.ASSOCIATED);
                        delayBeforeFinish();
                        return;
                    }


                }

                // We are connected
                if (!isConnectedToTargetNetwork()) {
                    state = STATE_WIFI_ON;
                    logInfo(TAG, "Starting wifi scan...");
                    wifi.startScan();
                }
            }
        }
    };

    /**
     * WIFI state callback - Listening for network scan completion
     */
    private BroadcastReceiver wifiScanResultsReceiver = new BroadcastReceiver() {
        public void onReceive(Context c, Intent intent) {

            Logger.logWarning(TAG, "WifiScanResultsReceiver - onReceive");

            // Don't care unless wifi is on
            if (state != STATE_WIFI_ON) {
                return;
            }

            // Check if we are already connected to target network
            if (isConnectedToTargetNetwork()) {
                sendCallbackMessage(handler, WifiStatus.ASSOCIATED);
                delayBeforeFinish();
                return;
            }

            // Check if the target network showed up in the scan
            if (isOurNetworkVisible()) {
                logInfo(TAG, "Scan found our ESSID:" + targetSSID);
                connectToVisibleNetwork();
            } else {
                logInfo(TAG, "Scan DID NOT FIND ESSID:" + targetSSID);
            }

        }
    };


    /**
     * method to return the current WIFI connectivity state
     *
     * @param targetSSID the network SSID we are hoping to be associated with
     * @return connection status
     */
    public WifiStatus getStatus(String targetSSID) {
        // Get a temporary WiFiManager instance since this is a static method

        // Check if wifi is on
        if (!wifi.isWifiEnabled()) {
            return WifiStatus.WIFI_OFF;
        }

        // Check if associated to anything
        WifiInfo wifiInfo = wifi.getConnectionInfo();
        if (wifiInfo == null || wifiInfo.getSSID() == null) {
            return WifiStatus.WIFI_ON;
        }

        // Check if associated to given SSID
        if (wifiInfo.getSSID().equals(targetSSID)) {
            return WifiStatus.ASSOCIATED;
        }

        // Check if given SSID is visible
        List<ScanResult> wifiList = wifi.getScanResults();
        for (ScanResult info : wifiList) {
            if (targetSSID.equals(info.SSID)) {
                return WifiStatus.SSID_VISIBLE;
            }
        }

        return WifiStatus.SSID_NOT_VISIBLE;

    }

    /**
     * Method to turn off WiFi
     *
     * @param context the callers application context
     * @return true if successful
     */
    public boolean turnOffWifi(Context context) {
        // Get a temporary WiFiManager instance since this is a static method
        return wifi.setWifiEnabled(false);
    }

    /**
     * Sends a message to the callback.
     *
     * @param callback the callback to send to
     */
    private static void sendCallbackMessage(Handler callback, WifiStatus status) {
        if (null != callback) {
            Message message = callback.obtainMessage();
            if (null != message) {
                message.obj = status;
                callback.sendMessage(message);
            }
        }
    }

    /**
     * Connects to the given ESSID.  Turns on WiFi if necessary.
     * Once the operation is complete (whether successful or not),
     * it sends a message to the given Handler with the state of the WiFi connection.
     */
    public void connectToTargetNetwork() {

        // Add timeout override to get out no matter what happens...
        timeoutHandler = new Handler();
        timeoutHandler.postDelayed(masterCompletionTimeout, timeout);

        state = STATE_UNKNOWN;

        // Check if we are already connected to target network
        if (isConnectedToTargetNetwork()) {
            sendCallbackMessage(handler, WifiStatus.ASSOCIATED);
            return;
        }

        registerReceivers();

        // Check if WIFI is turned on
        // Not enabled, turn it on!
        if (!wifi.isWifiEnabled()) {
            logInfo(TAG, "Enabling WIFI...");
            state = STATE_WIFI_OFF;
            boolean success = wifi.setWifiEnabled(true);
            if (!success) {
                sendCallbackMessage(handler, WifiStatus.WIFI_OFF);
            }
            // Wait for connection callback
            return;
        }

        // We are connected, check if target SSID is visible
        state = STATE_WIFI_ON;

        logInfo(TAG, "Starting wifi scan...");
        wifi.startScan();


    }

    public void registerReceivers() {
        // Register system WIFI state callbacks
        reactContext.getApplicationContext().registerReceiver(wifiStateReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
        reactContext.getApplicationContext().registerReceiver(wifiScanResultsReceiver, new IntentFilter(android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
    }

    /**
     * Perform internal cleanup before returning response to caller
     */
    public void cleanupConnectToTargetNetwork() {
        logInfo(TAG, "cleanupConnectToTargetNetwork");

        // Unregister all internal WiFi state receivers
        if (reactContext.getApplicationContext() != null) {
            // Unregister all our WIFI status receivers
            try {
                if (null != wifiStateReceiver) {
                    reactContext.getApplicationContext().unregisterReceiver(wifiStateReceiver);
                }
            } catch (Exception e) {
                logError(TAG, e.getMessage());
            }

            try {
                if (null != wifiScanResultsReceiver) {
                    reactContext.getApplicationContext().unregisterReceiver(wifiScanResultsReceiver);
                }
            } catch (Exception e) {
                logError(TAG, e.getMessage());
            }
        }

        // Cancel our master timeout
        if (timeoutHandler != null) {
            try {
                timeoutHandler.removeCallbacks(masterCompletionTimeout);
            } catch (Exception e) {
                logError(TAG, e.getMessage());
            }

            timeoutHandler = null;
        }

        try {
            state = STATE_UNKNOWN;
            // Get the final WiFi status and send it back to the caller
            WifiStatus status = getStatus(targetSSID);
            logInfo(TAG, "cleanupConnectToTargetNetwork - WiFi status=" + status.getName());
            sendCallbackMessage(handler, status);
        } catch (Exception e) {
            logError(TAG, "Error IN Wifi :: " + e);
        }

    }

    /**
     * Provides a slight delay before sending a results message to the caller.
     * This method is used when the requested network connection has been made successfully.
     * We have seen that when the OS reports the WiFi is ready, it might actually not be for a couple more seconds.
     * So we impart a slight delay to cover this.
     */
    private void delayBeforeFinish() {
        if (timeoutHandler != null) {
            timeoutHandler.removeCallbacks(masterCompletionTimeout);
        }
        if (timeoutHandler == null) {
            timeoutHandler = new Handler();
        }
        timeoutHandler.postDelayed(masterCompletionTimeout, DELAY_AFTER_CONNECTION_TIMEOUT);
    }

    /**
     * Connect to our target SSID.
     * A prerequisite to calling this function is that the SSID is visible from a network scan.
     */
    private void connectToVisibleNetwork() {
        logInfo(TAG, "connectToVisibleNetwork");

        // SSID is visible, check if it is configured
        state = STATE_SSID_VISIBLE;

        if (state == STATE_SSID_ASSOCIATING) {
            logError(TAG, "Associating now...");
            return;
        }

        // Check if the target SSID is configured on this device
        int networkId = isNetworkConfigured(targetSSID);
        logInfo(TAG, "Our network is configured returned:" + networkId);
        if (networkId < 0) {
            // Network not configured, Add the network
            logInfo(TAG, "Adding our network to configuration...");
            WifiConfiguration wifiConfig = setWifiConfiguration(targetSSID, WifiConfiguration.KeyMgmt.NONE);

            networkId = wifi.addNetwork(wifiConfig);
            logInfo(TAG, "addNetwork returned: " + networkId);
            if (networkId < 0) {
                return;
            }

            // Network added, save the changes
            wifi.saveConfiguration();
        }

        setWifiConfiguration(targetSSID, WifiConfiguration.KeyMgmt.NONE);

        wifi.disconnect();
        //wifi.saveConfiguration();
        // Network is configured on this device
        state = STATE_SSID_CONFIGURED;

        // Connect to network
        state = STATE_SSID_ASSOCIATING;
        boolean success = wifi.enableNetwork(networkId, true);

        //c2();
        wifi.reconnect();

//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            ConnectivityManager.setProcessDefaultNetwork(networkId);
//        }
        //ConnectivityManager.
        logInfo(TAG, "Enable our SSID returned:" + success);

        if (success) {
            logInfo(TAG, "connectToVisibleNetwork, Success...");
        }

        //connectToHost2(getReactApplicationContext(), targetSSID, "");
        return;
    }


    @NonNull
    private WifiConfiguration setWifiConfiguration(String targetSSID, int none) {
        WifiConfiguration wc = new WifiConfiguration();
        wc.SSID = formatSSIDWithQuotes(targetSSID);
        wc.hiddenSSID = false;
      /*  wifiConfig.priority = 1;
        wifiConfig.allowedKeyManagement.set(none);
        wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wifiConfig.allowedKeyManagement.set(none);
        wifiConfig.status = WifiConfiguration.Status.ENABLED;*/
        wc.status = WifiConfiguration.Status.ENABLED;
        wc.priority = 1;
        wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);

        wc.allowedAuthAlgorithms.set(0);
        wc.status = 2;

        wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
        wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        assignHighestPriority(wc);
        //wifi.updateNetwork(wc);
        return wc;
    }

    /**
     * Check if our target SSID is visible to the WIFI radio
     *
     * @return true if visible
     */
    public boolean isOurNetworkVisible() {

        // Get a list of visible SSID's and iterate through them
        List<ScanResult> wifiList = wifi.getScanResults();
        for (ScanResult info : wifiList) {
            Logger.logWarning(TAG, "Scan found ESSID:" + info.SSID + ", Strength :: " + info.level);
            // Check if each one is ours
            if (null != targetSSID && targetSSID.equals(info.SSID)) {
                return true;
            }
        }
        return false;
    }

    /* Check the strength of the WiFi
        0-3, 3=good
     */
    public boolean isInRange() {
        // Get a list of visible SSID's and iterate through them
        List<ScanResult> wifiList = wifi.getScanResults();
        for (ScanResult info : wifiList) {
            if (null != targetSSID && targetSSID.equals(info.SSID)) {
                int rssi = wifi.getConnectionInfo().getRssi();
                int level = wifi.calculateSignalLevel(rssi, 3);
                Logger.logWarning(TAG, "Scan found ESSID:" + info.SSID + ", Strength :: " + info.level + " , Calculated Level :: " + level);
                return level > 0;
            }
        }
        return false;
    }

    /**
     * Check if we are connected to the target SSID
     *
     * @return
     */
    private boolean isConnectedToTargetNetwork() {
        try {
            wifi = (android.net.wifi.WifiManager) reactContext.getApplicationContext().getSystemService(WIFI_SERVICE);
            if (null == wifi) {
                return false;
            }
            if (!wifi.isWifiEnabled()) {
                return false;
            }
            WifiInfo wifiInfo = wifi.getConnectionInfo();

            if (null != targetSSID) {
                targetSSID = targetSSID.replaceAll("\"", "");
            }
            String ssid = wifiInfo.getSSID();
            if (null != ssid) {
                ssid = ssid.replaceAll("\"", "");
            }
            return wifiInfo != null && wifiInfo.getSSID() != null && ssid.equals(targetSSID);
        } catch (Exception e) {
            logError(TAG, "<< isConnectedToTargetNetwork >> " + e);
            return false;
        }
    }

    /**
     * Check if the given network is configured on this device
     *
     * @param ssid the SSID to check
     * @return the networkId of this SSID or -1 if not found
     */
    private int isNetworkConfigured(String ssid) {
        logInfo(TAG, "isNetworkConfigured for >" + ssid + "<");

        // The SSID's returned by the system have quotes around them
        String formattedSSID = formatSSIDWithQuotes(ssid);

        try {
            // Get the configured networks (SSID's) and iterate though them
            List<WifiConfiguration> networksList = wifi.getConfiguredNetworks();
            for (WifiConfiguration config : networksList) {
                logInfo(TAG, "Config - essid =: " + config.SSID + ", id =" + config.networkId);

                // Is this our SSID?
                if (formattedSSID.equals(config.SSID)) {
                    logInfo(TAG, "Network IS configured - essid=:" + config.SSID + ", id=" + config.networkId);
                    wifi.saveConfiguration();
                    // Return the internal network id of this SSID
                    return config.networkId;
                }
            }
        } catch (Exception e) {
            logInfo(TAG, "isNetworkConfigured exception - " + e.getMessage());
        }

        // The given SSID was not found
        return -1;
    }

    private String formatSSIDWithQuotes(String ssid) {
        return "\"" + ssid + "\"";
    }

    public static void displayLocationSettingsRequest(final Context activity) {

        final Message message = new Message();

        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(activity)
                .addApi(LocationServices.API).build();
        googleApiClient.connect();

        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(30 * 1000);
        locationRequest.setFastestInterval(5 * 1000);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest);
        builder.setAlwaysShow(true);

        PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult result) {
                final Status status = result.getStatus();
                final LocationSettingsStates state = result.getLocationSettingsStates();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied. The client can initialize location
                        // requests here.
                        message.arg1 = 1;
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        message.arg1 = 0;
                        // Location settings are not satisfied. But could be fixed by showing the user
                        // a dialog.
//                        try {
//                            // Show the dialog by calling startResolutionForResult(),
//                            // and check the result in onActivityResult().
//                            //status.startResolutionForResult(activity, 1000);
//                        } catch (IntentSender.SendIntentException ignored) {}
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        // Location settings are not satisfied. However, we have no way to fix the
                        // settings so we won't show the dialog.
                        message.arg1 = 0;
                        break;
                }
            }
        });
    }

    //To tell OS to give preference to this network
    private void assignHighestPriority(WifiConfiguration config) {
        List<WifiConfiguration> configuredNetworks = wifi.getConfiguredNetworks();
        if (configuredNetworks != null) {
            for (WifiConfiguration existingConfig : configuredNetworks) {
                if (config.priority <= existingConfig.priority) {
                    config.priority = existingConfig.priority + 1;
                }
            }
        }
    }


    /////


}

1 个答案:

答案 0 :(得分:0)

我找到决定。您必须每隔1秒为不同的站点添加一个流量。