프로그래밍 방식으로 Android의 특정 Wi-Fi 네트워크에 어떻게 연결합니까?


294

사용 가능한 Wi-Fi 네트워크 목록을 표시하고 사용자가 선택한 네트워크에 연결하는 앱을 디자인하고 싶습니다.

스캔 결과를 보여주는 부분을 구현했습니다. 이제 스캔 결과 목록에서 사용자가 선택한 특정 네트워크에 연결하려고합니다.

어떻게해야합니까?



이것은 나를 위해 WPA2와 WEP를 위해 일했다 : stackoverflow.com/a/29575563/7337517
Kundan

답변:


441

다음 WifiConfiguration과 같은 인스턴스 를 작성해야합니다 .

String networkSSID = "test";
String networkPass = "pass";

WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";   // Please note the quotes. String should contain ssid in quotes

그런 다음 WEP 네트워크의 경우 다음을 수행해야합니다.

conf.wepKeys[0] = "\"" + networkPass + "\""; 
conf.wepTxKeyIndex = 0;
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); 

WPA 네트워크의 경우 다음과 같이 비밀번호 문구를 추가해야합니다.

conf.preSharedKey = "\""+ networkPass +"\"";

개방형 네트워크의 경우 다음을 수행해야합니다.

conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);

그런 다음 Android wifi 관리자 설정에 추가해야합니다.

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

마지막으로 활성화해야하므로 Android가 연결해야합니다.

List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
for( WifiConfiguration i : list ) {
    if(i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) {
         wifiManager.disconnect();
         wifiManager.enableNetwork(i.networkId, true);
         wifiManager.reconnect();               

         break;
    }           
 }

UPD : WEP의 경우 암호가 16 진수 인 경우 따옴표로 묶을 필요가 없습니다.


5
잘 작동합니다! 고맙습니다 :)하지만 한 가지 더 묻고 싶습니다. allowedPairwiseCipher, allowedAuthALgorithms 및 allowedProtocols를 설정할 필요가 없습니까? 설정할 특정 속성을 결정하는 방법; WEP 네트워크 용 GroupCipher에 대해 WEP40을 설정하셨습니까?
Vikram Gupta

8
한 가지 언급하는 것을 잊었습니다. WEP의 경우 비밀번호가 16 진인 경우 따옴표로 묶을 필요는 없습니다.
kenota

8
좋은 해결책에 감사드립니다. 연결이 성공했는지 확인하는 방법을 자세히 설명해 주시겠습니까? 예를 들어, 사용자가 잘못된 비밀번호를 입력하고 이에 대해 알려야합니다.
Pascal Klein

3
원하는 Wi-Fi 핫스팟이 암호를 전혀 사용하지 않는 경우는 어떻습니까? .preSharedKey = null; 아니면 .preSharedKey = ""; 어느 것이 맞습니까? @kenota
gumuruh

6
그것은 나를 위해 작동하지 않습니다 : 그것은 새로운 와이파 이에 연결하는 대신 이전에 기억 된 와이파 이에 직접 다시 연결합니다.
Virthuss

138

이전의 대답은 작동 하지만,이 솔루션은 실제로 간단 할 수 있습니다. WifiManager를 통해 네트워크를 추가 할 때 네트워크 ID를 가져 오므로 구성된 네트워크 목록을 반복 할 필요가 없습니다.

따라서 완벽하고 단순화 된 솔루션은 다음과 같습니다.

WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = String.format("\"%s\"", ssid);
wifiConfig.preSharedKey = String.format("\"%s\"", key);

WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE);
//remember id
int netId = wifiManager.addNetwork(wifiConfig);
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();

1
비밀번호를 사용하지 않는 경우 .preSharedKey = null을 넣어야합니다. 아니면 @seanloyola 빈 문자열을 넣어야합니까?
gumuruh

2
@MuhammedRefaat 이미 다른 네트워크에 연결되어있는 경우 연결을 끊습니다.
sean loyola

1
@gumuruh는 키가 필요하지 않은 경우 presharedkey 객체를 전혀 포함하지 않아도됩니다.
sean loyola

7
당신은 진정한 부울 disableOthers를 사용하는 경우 enableNetwork의 자바 독에 따라, 당신은 분리하거나 연결할 필요 없다, 그것은 당신을 위해 모두를 할 것
NikkyD

12
아마도 CHANGE_WIFI_STATE권한이 필요하다고 언급해야 합니다.
ThomasW

27

WIFI 네트워크를 연결하기 전에 WIFI 네트워크의 보안 유형을 확인해야합니다. ScanResult 클래스에는 기능이 있습니다. 이 필드는 네트워크 유형을 제공합니다

참조 : https://developer.android.com/reference/android/net/wifi/ScanResult.html#capabilities

WIFI 네트워크 에는 세 가지 유형 이 있습니다.

먼저 WifiConfiguration 객체를 인스턴스화하고 네트워크의 SSID를 채우고 (큰 따옴표로 묶어야 함) 초기 상태를 비활성화로 설정하고 네트워크의 우선 순위를 지정하십시오 (40 정도의 숫자가 잘 작동하는 것 같습니다).

WifiConfiguration wfc = new WifiConfiguration();

wfc.SSID = "\"".concat(ssid).concat("\"");
wfc.status = WifiConfiguration.Status.DISABLED;
wfc.priority = 40;

더 복잡한 부분을 위해 : 네트워크의 보안 모드를 지정하기 위해 WifiConfiguration의 여러 멤버를 채워야합니다. 개방형 네트워크 용.

wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wfc.allowedAuthAlgorithms.clear();
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

WEP를 사용하는 네트워크의 경우; WEP 키도 큰 따옴표로 묶습니다.

wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wfc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wfc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

if (isHexString(password)) wfc.wepKeys[0] = password;
else wfc.wepKeys[0] = "\"".concat(password).concat("\"");
wfc.wepTxKeyIndex = 0;

WPA 및 WPA2를 사용하는 네트워크의 경우 둘 중 하나에 동일한 값을 설정할 수 있습니다.

wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wfc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

wfc.preSharedKey = "\"".concat(password).concat("\"");

마지막으로 WifiManager의 알려진 목록에 네트워크를 추가 할 수 있습니다

WifiManager wfMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
int networkId = wfMgr.addNetwork(wfc);
if (networkId != -1) {
 // success, can call wfMgr.enableNetwork(networkId, true) to connect
} 

우선 순위에 대한 메모, 약 4000 전화 번호에 근무했습니다. 이 부분을 좀 더 역동적으로 만드는 것이 가장 좋습니다 (기존 구성 등 반복)
Sam

어떻게 와이파이 ScanResult에 대한 SSID의 네트워크 보안 유형을 얻을 수

@shantanu 자세한 내용은 다음을 확인하십시오. stackoverflow.com/questions/6866153/…
Kalpesh Gohel

삼성 기기에서 비밀번호 문구는 해시 문자열입니다. 그리고 코드가 작동하지 않습니다. 당신은 그것을 확인합니까?
Nguyen Minh Binh

sim 유형 wifi의 EAP를 연결하기위한 샘플을 제공 할 수 있습니까?
Prashanth Debbadwar

19

@ raji-ramamoorthi 및 @kenota의 신용

나를 위해 일한 해결책은이 스레드에서 위의 기고자들의 조합입니다.

ScanResult여기에 도착 하는 과정입니다.

WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled() == false) {
            Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled", Toast.LENGTH_LONG).show();
            wifi.setWifiEnabled(true);
        }

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context c, Intent intent) {
                 wifi.getScanResults();
            }
        };

고지 unregisteronPause& onStop사는이unregisterReceiver(broadcastReceiver);

public void connectWiFi(ScanResult scanResult) {
        try {

            Log.v("rht", "Item clicked, SSID " + scanResult.SSID + " Security : " + scanResult.capabilities);

            String networkSSID = scanResult.SSID;
            String networkPass = "12345678";

            WifiConfiguration conf = new WifiConfiguration();
            conf.SSID = "\"" + networkSSID + "\"";   // Please note the quotes. String should contain ssid in quotes
            conf.status = WifiConfiguration.Status.ENABLED;
            conf.priority = 40;

            if (scanResult.capabilities.toUpperCase().contains("WEP")) {
                Log.v("rht", "Configuring WEP");    
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

                if (networkPass.matches("^[0-9a-fA-F]+$")) {
                    conf.wepKeys[0] = networkPass;
                } else {
                    conf.wepKeys[0] = "\"".concat(networkPass).concat("\"");
                }

                conf.wepTxKeyIndex = 0;

            } else if (scanResult.capabilities.toUpperCase().contains("WPA")) {
                Log.v("rht", "Configuring WPA");

                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

                conf.preSharedKey = "\"" + networkPass + "\"";

            } else {
                Log.v("rht", "Configuring OPEN network");
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedAuthAlgorithms.clear();
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            }

            WifiManager wifiManager = (WifiManager) WiFiApplicationCore.getAppContext().getSystemService(Context.WIFI_SERVICE);
            int networkId = wifiManager.addNetwork(conf);

            Log.v("rht", "Add result " + networkId);

            List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
            for (WifiConfiguration i : list) {
                if (i.SSID != null && i.SSID.equals("\"" + networkSSID + "\"")) {
                    Log.v("rht", "WifiConfiguration SSID " + i.SSID);

                    boolean isDisconnected = wifiManager.disconnect();
                    Log.v("rht", "isDisconnected : " + isDisconnected);

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

                    boolean isReconnected = wifiManager.reconnect();
                    Log.v("rht", "isReconnected : " + isReconnected);

                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

5

기기가 Wi-Fi 구성 (이미 저장 됨)을 알고 있으면 로켓 과학을 우회 할 수 있습니다. SSID가 일치하는지 확인하기 위해 구성을 반복하십시오. 그렇다면 연결하고 돌아가십시오 .

권한 설정 :

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

잇다:

    try {
    String ssid = null;
    if (wifi == Wifi.PCAN_WIRELESS_GATEWAY) {
        ssid = AesPrefs.get(AesConst.PCAN_WIRELESS_SSID,
                context.getString(R.string.pcan_wireless_ssid_default));
    } else if (wifi == Wifi.KJ_WIFI) {
        ssid = context.getString(R.string.remote_wifi_ssid_default);
    }

    WifiManager wifiManager = (WifiManager) context.getApplicationContext()
            .getSystemService(Context.WIFI_SERVICE);

    List<WifiConfiguration> wifiConfigurations = wifiManager.getConfiguredNetworks();

    for (WifiConfiguration wifiConfiguration : wifiConfigurations) {
        if (wifiConfiguration.SSID.equals("\"" + ssid + "\"")) {
            wifiManager.enableNetwork(wifiConfiguration.networkId, true);
            Log.i(TAG, "connectToWifi: will enable " + wifiConfiguration.SSID);
            wifiManager.reconnect();
            return null; // return! (sometimes logcat showed me network-entries twice,
            // which may will end in bugs)
        }
    }
} catch (NullPointerException | IllegalStateException e) {
    Log.e(TAG, "connectToWifi: Missing network configuration.");
}
return null;

5

WPA / WPA2에 대한 귀하의 답변이 효과가없는 이유를 이해하기 위해 머리를 아프게했습니다.

conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);

WPA 네트워크에 필수입니다 !!!!

이제는 작동합니다 :)


4

이것은 특정 Wi-Fi에 연결하기 위해 서브 클래스 화 할 수있는 활동입니다 : https://github.com/zoltanersek/android-wifi-activity/blob/master/app/src/main/java/com/zoltanersek/androidwifiactivity/ WifiActivity.java

이 액티비티를 서브 클래 싱하고 해당 메소드를 구현해야합니다.

public class SampleActivity extends WifiBaseActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  }

  @Override
  protected int getSecondsTimeout() {
      return 10;
  }

  @Override
  protected String getWifiSSID() {
      return "WifiNetwork";
  }

  @Override
  protected String getWifiPass() {
      return "123456";
  }
}

링크 다운 새로운 것을 줄 수 있습니까?
StartCoding

4

API 레벨 29에서는 WifiManager.enableNetwork()메소드가 사용되지 않습니다 . Android API 설명서에 따라 ( 여기에서 확인 ) :

  1. Wi-Fi 네트워크 연결을 트리거하는 새로운 메커니즘에 대해서는 WifiNetworkSpecifier.Builder # build ()를 참조하십시오.
  2. Wi-Fi에 자동 연결할 때 고려할 Wi-Fi 네트워크를 추가하는 새 API에 대해서는 addNetworkSuggestions (java.util.List), removeNetworkSuggestions (java.util.List)를 참조하십시오. 호환성 참고 : Build.VERSION_CODES.Q 이상을 대상으로하는 응용 프로그램의 경우이 API는 항상 false를 반환합니다.

API 레벨 29부터 WiFi 네트워크에 연결하려면 WifiNetworkSpecifier 합니다. https://developer.android.com/reference/android/net/wifi/WifiNetworkSpecifier.Builder.html#build () 에서 예제 코드를 찾을 수 있습니다.


새로운 WifiNetWorkSpecifier.Builder를 사용하여 WEP 네트워크에 연결할 수 있습니까? 빌더에 WEP 비밀번호 문구를 추가하는 방법을 찾을 수 없습니다.
Dieter4

숫자 1이 작동하지 않는 것 같습니다. 콜백이 있습니까?
파이 잔 미르

1

또한 네트워크에 연결하려고했습니다. 위에서 제안한 솔루션 중 어느 것도 hugerock t70에서 작동하지 않습니다. 기능 wifiManager.disconnect (); 현재 네트워크에서 연결을 끊지 않습니다. 따라서 지정된 네트워크에 다시 연결할 수 없습니다. 위의 코드를 수정했습니다. 나를 위해 코드 bolow는 완벽하게 작동합니다.

String networkSSID = "test";
String networkPass = "pass";

WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";   
conf.wepKeys[0] = "\"" + networkPass + "\""; 
conf.wepTxKeyIndex = 0;
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); 
conf.preSharedKey = "\""+ networkPass +"\"";

WifiManager wifiManager =         
(WifiManager)context.getSystemService(Context.WIFI_SERVICE);    

int networkId = wifiManager.addNetwork(conf);
wifi_inf = wifiManager.getConnectionInfo();

/////important!!!
wifiManager.disableNetwork(wifi_inf.getNetworkId());
/////////////////

wifiManager.enableNetwork(networkId, true);

Android 10에서 오류가 발생했습니다.UID nnnnn does not have permission to update configuration xxxx. MD_START_CONNECT but no requests and connected, but app does not have sufficient permissions, bailing.
Luis A. Florit

0

이 방법을 시도하십시오. 이것은 정말 쉽습니다:

public static boolean setSsidAndPassword(Context context, String ssid, String ssidPassword) {
    try {
        WifiManager wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
        Method getConfigMethod = wifiManager.getClass().getMethod("getWifiApConfiguration");
        WifiConfiguration wifiConfig = (WifiConfiguration) getConfigMethod.invoke(wifiManager);

        wifiConfig.SSID = ssid;
        wifiConfig.preSharedKey = ssidPassword;

        Method setConfigMethod = wifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
        setConfigMethod.invoke(wifiManager, wifiConfig);

        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.