Android/WI-FI | Posted by 덩치 2015.05.08 11:13

Wifi 비활성화일 때 스캔하는 방법

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO



일반적으로 많이 알려진 Wifi Scan 방법은 Wifi 활성화 돼 있을때만 가능하다.


때문에 Wifi Scan이 필요할 때, 사용자의 Wifi를 강제로 Enable 시킨 뒤 스캔을 하고, 스캔이 끝다면 다시 비활성화 시키는


방식으로 많이들 구현한다.


그런데 Android 버전 4.3(SDK 18)부터 추가된 '항상 검색 허용' 설정을 이용하면 Wifi비활성화 상태라


Wifi스캔할 수 있다.




해당 옵션이 활성화 돼 있을때만 위와같은 동작이 가능하다.


소스코드상으로는 해당 설정을 컨트롤 할 수 없으며, 사용자가 직접 설정할 수 있다.



따라서 SDK 버전이 18 이상인지, '항상 검색 허용' 설정이 활성화상태인지 체크를 한 다음


조건을 만족하지 않는다면 기존 방식을 이용하고, 만족한다면 Wifi를 건들지 않고 바로 스캔을 진행할 수 있다.



위 조건을 구현하는 방법은 아래와 같다.


if (Build.VERSION.SDK_INT >= 18) {  //  4.3 버전 이상인지 체크한다.

if (mWM.isScanAlwaysAvailable()) {  //  항상검색 허용 설정이 활성화상태인지 체크한다.

mWM.startScan();  // 바로 스캔 실행

return;

}

}

mWM.setWifiEnabled(true);

// 위 조건을 만족하지 않는다면 Wifi 상태에 변화를 줘서 BroadcastReceiver에 액션이 들어오게 하여 스캔을 진행한다.

// 자세한 방법은 http://biig.tistory.com/14 참조


끝.







펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO




private void getPackageList() {

PackageManager pm = this.getPackageManager();


List<PackageInfo> packs =                   getPackageManager().getInstalledPackages(PackageManager.PERMISSION_GRANTED);

Log.i("TAG", "===================================================");

for (PackageInfo pack : packs) {

Log.d("TAG", "| name    : " + pack.packageName);

      Log.d("TAG", "| package : " + pack.packageName);

      Log.d("TAG", "| version : " + pack.versionName);

}

Log.i("TAG", "===================================================");

}



휴대폰에 설치 된 패키지명과 어플명, 버전을 가져온다.



public void onRemovePackage(String removePackage) {

Uri uri = Uri.fromParts("package", removePackage, null);

Intent intent = new Intent(Intent.ACTION_DELETE, uri);

startActivity(intent);

}


removePackage로 받아 온 패키지명의 어플을 삭제하겠냐는 팝업이 나타나고, 해당 패키지를 삭제한다.


호출은 


onRemovePAckage("com.example.test");




펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

wifi를 검색하는 방법에 대해서는 이전 글에서 알아보았다.


wifi에 연결하기 위해서는 보안방식과 비밀번호, ssid가 필요한데

보안방식과 ssid는 이전글의 ScanResult에서 뽑아낼 수가 있다.


비밀번호를 모르면 당연히 보안이 걸려있는 wifi에는 연결이 불가능.


일단 소스를 살펴보자


open일때

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.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);

wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);

wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

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.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);

wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

wfc.wepKeys[0] = "123456abcd";   <<--이부분중요. \"부분 빼고 그냥 비밀번호만 넣는다

wfc.wepTxKeyIndex = 0;

wpa나 wpa2일때

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

wfc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);

wfc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);

wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);

wfc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);

wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);

wfc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);

wfc.preSharedKey = "\"".concat("123456abcd").concat("\"");


이렇게 보안방식별로 설정 방법이 다르다.

wpa와 wpa2는 설정이 같다고 하는데 필자의경우 wpa방식은 연결이 안되더라.

실제 테스트해본건 wpa2와 wep, open밖에 없다.

참고로 ScanResult.capabilites에서 뱉어주는 보안방식이 실제 open, web, wpa로 나오는건 아니고

[WPA-PSK-TKIP+CCMP][ESS]

[WPA2-PSK-CCMP][WPS][ESS]  이런식이며, 같은 방식도 length가 다른경우가 있다.

이부분은 알아서 잘 처리해주리라 믿고,



먼저 공통설정을

WifiConfiguration wfc = new WifiConfiguration(); (WifiConfiguration는 전역변수,지역변수 알아서 상황에 맞게 조절한다)

wfc = new WifiConfiguration();

wfc.SSID = "\"".concat(ssid 입력).concat("\"");

wfc.status = WifiConfiguration.Status.DISABLED;

wfc.priority = 40;

이렇게 해준다.


그리고 위의 보안방식에 따른 설정을 해 주고,


int networkId = wm.addNetwork(wfc);

if (networkId != -1) {

wm.enableNetwork(networkId, true);

}


이렇게 해주면 해당하는 wifi에 연결이 완료된다.

open형의 경우에는 level(신호세기)에 따라 정렬을 해 주고, 위의 소스를 적용시키면 가장 신호가 센놈으로

자동으로 연결될듯하다.



-끝-


Android/WI-FI | Posted by 덩치 2013.10.23 16:08

Wifi 목록 검색하는법

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


전역변수로 

ScanResult scanResult;

WifiManager wm;

List apList;


WifiManager 초기화

wm = (WifiManager) getSystemService(WIFI_SERVICE);


검색

wm.startScan(); 때려주고


IntentFilter filter = new IntentFilter();

filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

registerReceiver(wifiReceiver, filter);

이렇게 브로드캐스트리시버를 사용해줘야한다.

이유는 스캔이 끝났을 때를 체크하기 위해서이다


브로드캐스트리시버 선언

private BroadcastReceiver wifiReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

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

searchWifi();

}

}

};

스캔이끝났다는 방송이 전달되면 searchWifi() 호출


searchWifi를 보면

public void searchWifi() {

apList = wm.getScanResults();

if (wm.getScanResults() != null) {

int size = apList.size();

for (int i = 0; i < size; i++) {

scanResult = (ScanResult) apList.get(i);

}

}

}


이렇게 하면 scanResult에 Wifi에 대한 정보들이 입력된다. 호출은 반복문 안에서나 원하는 위치에서

scanResult.SSID 등으로 이용할 수 있다.

Wifi가 on인지 off인지 모를때는 필터액션에 와이파이 스테이트 체인지액션까지 넣어주면 더욱좋다


-끝-