Notice
Recent Posts
Recent Comments
Link
투케이2K
141. (TWOK/UTIL) [Android/Java] C_Wifi_Ap_Module : 와이파이 및 모바일 핫스팟 관련 기능 사용 모듈 - Wifi , Ap 본문
투케이2K 유틸파일
141. (TWOK/UTIL) [Android/Java] C_Wifi_Ap_Module : 와이파이 및 모바일 핫스팟 관련 기능 사용 모듈 - Wifi , Ap
투케이2K 2024. 11. 6. 20:23[설 명]
프로그램 : Android / Java
설 명 : C_Wifi_Ap_Module : 와이파이 및 모바일 핫스팟 관련 기능 사용 모듈 - Wifi , Ap
[소스 코드]
package com.example.javaproject.C_Module;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkSpecifier;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import androidx.core.app.ActivityCompat;
import com.example.javaproject.C_Permission;
import com.example.javaproject.C_StateCheck;
import com.example.javaproject.C_Util;
import com.example.javaproject.S_FinalData;
import com.example.javaproject.S_Log;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.reactivex.rxjava3.core.Observable;
public class C_Wifi_Ap_Module {
/**
* // --------------------------------------------------------------------------------------
* TODO [클래스 설명]
* // --------------------------------------------------------------------------------------
* 1. [설명] : 와이파이 및 모바일 핫스팟 관련 기능 사용 모듈
* // --------------------------------------------------------------------------------------
* 2. 필요 퍼미션 :
*
* TODO [안드로이드 13 이상] : [근처 기기 스캔 + 와이파이 접근 + 위치 접근]
*
* <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
*
* <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
* <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
*
* <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
* <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
* <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
* <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
* <uses-feature android:name="android.hardware.location.network"/>
*
*
* TODO [안드로이드 13 미만] : [와이파이 접근 + 위치 접근]
*
* <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
* <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
*
* <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
* <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
* <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
* <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
* <uses-feature android:name="android.hardware.location.network"/>
* // --------------------------------------------------------------------------------------
* 3. 와이파이 및 기능 사용간 참고 사항 :
*
* - 와이파이 스캔 기능은 1분에 4회 이상 스캔 시 OS 에서 제한 발생 (개발자 모드에서 제한 해제 가능)
* // --------------------------------------------------------------------------------------
* */
/**
* // --------------------------------------------------------------------------------------
* TODO [빠른 로직 찾기 : 주석 로직 찾기]
* // --------------------------------------------------------------------------------------
* TODO [와이파이 관련]
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : observableWifiScanList : 와이파이 리스트 스캔
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : observableSetWifiConnection : WPA/WPA2 형식 와이파이 연결 수행
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : observableWifiInfo : 현재 연결 된 와이파이 정보 확인
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : getWifiRssiMsg : 와이파이 RSSI 신호 강도 세기 메시지 확인
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : getWifiPasswordMsg : 와이파이 비밀번호 설정 여부 메시지 포맷 출력
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : getWifiCreateQrData : 와이파이 연결에 필요한 QR 코드 생성 데이터 포맷
* // --------------------------------------------------------------------------------------
* [SEARCH FAST] : getWifiGHz : 와이파이 GHZ 및 채널 확인
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*/
// ------------------------------------------------------------------------------------------
// TODO [전역 변수 선언]
// ------------------------------------------------------------------------------------------
private static String ACTIVITY_NAME = "C_Wifi_Ap_Module";
private static int WIFI_SCAN_TIMEOUT = 30; // [와이파이 스캔 타임 아웃]
// ------------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : observableWifiScanList : 와이파이 리스트 스캔
// ------------------------------------------------------------------------------------------
// TODO [호출 방법 소스 코드]
// -----------------------------------------------------------------------------------------
/*
try {
C_Wifi_Ap_Module.observableWifiScanList(A_Intro.this)
.subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
.observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
.subscribe(new Observer<List<ScanResult>>() { // [Observable.create 타입 지정]
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull List<ScanResult> value) {
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
S_Log._printStackTrace_(mContext, S_FinalData.LOG_BUG_STATE, null, e);
}
*/
// -----------------------------------------------------------------------------------------
static String WIFI_M_LOG = "";
static int WIFI_COUNT = 0;
static BroadcastReceiver mWifiScanReceiver = null;
public static Observable<List<ScanResult>> observableWifiScanList(Context mContext) {
// [로직 처리 실시]
return Observable.create(subscriber -> {
// [변수 초기화]
WIFI_M_LOG = "";
WIFI_COUNT = 0;
try {
// ===============================================================
S_Log._D_(ACTIVITY_NAME + " :: 와이파이 리스트 스캔 시작", null);
// ===============================================================
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// [퍼미션 권한 체크 실시]
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
// [퍼미션이 부여되어있지 않은 경우 종료]
WIFI_M_LOG = "[ERROR] : Wifi Scan Permission not Granted (와이파이 스캔에 필요한 권한을 확인해주세요. : GPS , Location)";
// ===============================================================
S_Log._E_("ERROR", new String[]{
"ERROR :: " + String.valueOf(WIFI_M_LOG)
});
// ===============================================================
// [리턴 반환 실시]
subscriber.onError(new Throwable(WIFI_M_LOG));
subscriber.onComplete();
} else {
// ---------------------------------------------------------------
// TODO [와이파이 리스트 스캔 실시]
// ---------------------------------------------------------------
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
wifiManager.startScan();
// List<ScanResult> scanResultList = wifiManager.getScanResults();
// ---------------------------------------------------------------
// ---------------------------------------------------------------
// TODO [핸들러 작업 예약 등록] : [와이파이 리시버 대기]
// ---------------------------------------------------------------
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
S_Log._E_(ACTIVITY_NAME + " :: 와이파이 스캔 에러 발생", new String[]{
"ERROR :: Wifi Scan Time Out"
});
// [에러 메시지 삽입]
WIFI_M_LOG = "[ERROR] : Wifi Scan Time Out";
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
try {
if (mWifiScanReceiver != null){
mContext.unregisterReceiver(mWifiScanReceiver);
}
}
catch (Exception es){
es.printStackTrace();
}
subscriber.onError(new Throwable(WIFI_M_LOG));
subscriber.onComplete();
}
}
}, WIFI_SCAN_TIMEOUT * 1000);
// ---------------------------------------------------------------
// ---------------------------------------------------------------
// TODO [리시버 설정 실시]
// ---------------------------------------------------------------
mWifiScanReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context c, Intent intent) {
if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
// ===============================================================
S_Log._W_(ACTIVITY_NAME + " :: mWifiScanReceiver onReceive", null);
// ===============================================================
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
List<ScanResult> scanResultList = wifiManager.getScanResults();
for (ScanResult result : scanResultList) {
HashMap<String, Object> map = new HashMap<>();
map.put("SSID", result.SSID); // [SSID]
map.put("BSSID", result.BSSID); // [BSSID]
map.put("level", result.level); // [신호 강도]
map.put("capabilities", result.capabilities); // [암호화 여부]
}
// [중복 데이터 제거]
HashSet hashSet = new HashSet<>(scanResultList);
// [리스트 변환]
List<ScanResult> distinctResultList = new ArrayList<>(hashSet);
WIFI_COUNT = distinctResultList.size();
// [로그 출력]
// ===============================================================
S_Log._W_(ACTIVITY_NAME + " :: 와이파이 스캔 완료", new String[]{
"SCAN COUNT :: " + String.valueOf(WIFI_COUNT),
"SCAN LIST :: " + String.valueOf(distinctResultList)
});
// ===============================================================
// ------------------------------------------------------
// TODO [핸들러 예약 작업 취소]
// ------------------------------------------------------
try {
if (handler != null){
handler.removeMessages(0);
handler.removeCallbacks(null);
}
}
catch (Exception ex){
ex.printStackTrace();
}
// ------------------------------------------------------
// TODO [리턴 데이터 반환]
// ------------------------------------------------------
try {
// [메시지 삽입]
WIFI_M_LOG = "SUCCESS";
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext(distinctResultList);
subscriber.onComplete();
}
// [등록한 리시버 해제]
mContext.unregisterReceiver(mWifiScanReceiver);
}
catch (Exception ex){
ex.printStackTrace();
}
}
}
};
// ---------------------------------------------------------------
// TODO [리시버 등록]
// ---------------------------------------------------------------
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mContext.registerReceiver(mWifiScanReceiver, intentFilter);
// ---------------------------------------------------------------
}
}
}, 0);
} catch (final Exception e){
S_Log._printStackTrace_(mContext, S_FinalData.LOG_BUG_STATE, null, e);
// ===============================================================
S_Log._E_(ACTIVITY_NAME + " :: 와이파이 스캔 에러 발생", new String[]{
"EXCEPTION :: " + String.valueOf(e.getMessage())
});
// ===============================================================
// ------------------------------------------------------
// TODO [리턴 데이터 반환]
// ------------------------------------------------------
try {
// [에러 메시지 삽입]
WIFI_M_LOG = "[EXCEPTION] : " + String.valueOf(e.getMessage());
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(WIFI_M_LOG));
subscriber.onComplete();
}
}
catch (Exception ex){
ex.printStackTrace();
}
}
});
}
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : observableSetWifiConnection : WPA/WPA2 형식 와이파이 연결 수행
// -----------------------------------------------------------------------------------------
// TODO [호출 방법 소스 코드]
// -----------------------------------------------------------------------------------------
/*
try {
C_Wifi_Ap_Module.observableSetWifiConnection(A_Webview.this, "TWOK", "t123456789")
.subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
.observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
.subscribe(new Observer<String>() { // [Observable.create 타입 지정]
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull String value) {
S_Log._F_(A_Webview.this, ACTIVITY_NAME + " :: onNext :: " + String.valueOf(value), null);
if (C_Util.stringNotNull(value) == true){
// -------------------------------------------------
// TODO [1]. 서버 소켓 통신을 하기 위한 PORT 선언
// -------------------------------------------------
int port = 18501;
// --------------------------------------
// TODO [2]. [서버 소켓 모듈 클래스 인스턴스 초기화]
// --------------------------------------
C_TcpIp_Server_Single_Socket_Module c_server_socket_module = C_TcpIp_Server_Single_Socket_Module.getInstance();
c_server_socket_module.setContext(A_Webview.this);
// --------------------------------------
// TODO [3]. [서버 소켓 활성 수행]
// --------------------------------------
if(c_server_socket_module.openServer(port) == true) { // [소켓 연결 상태 확인]
}
else {
S_Log._E_("서버 소켓 활성 실패", null);
}
}
}
@Override
public void onError(@NonNull Throwable e) {
S_Log._F_(A_Webview.this, ACTIVITY_NAME + " :: onError :: " + String.valueOf(e.getMessage()), null);
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
S_Log._printStackTrace_(mContext, S_FinalMsg.LOG_BUG_STATE, null, e);
}
*/
// -----------------------------------------------------------------------------------------
public static Observable<String> observableSetWifiConnection(Context mContext, String ssid, String password) {
/**
* -------------------------------------------
* [observableSetWifiConnection 메소드 설명]
* -------------------------------------------
* 1. WPA/WPA2 형식 와이파이 연결 수행
*
* -------------------------------------------
* 2. 필요 퍼미션 : [사전에 사용자로부터 퍼미션 인증을 모두 받아야 합니다]
*
* Manifest.permission.ACCESS_COARSE_LOCATION,
* Manifest.permission.ACCESS_FINE_LOCATION,
* Manifest.permission.ACCESS_WIFI_STATE,
* Manifest.permission.CHANGE_WIFI_STATE,
* Manifest.permission.ACCESS_NETWORK_STATE
*
* TODO : 안드로이드 13 이상 근처기기 권한 추가
* -------------------------------------------
* */
// [로직 처리 실시]
return Observable.create(subscriber -> {
// [변수 초기화]
final String[] M_LOG = {""};
try {
// ===============================================================
S_Log._D_("와이파이 연결 수행 시작", new String[]{
"CONNECTION SSID :: " + String.valueOf(ssid),
"CONNECTION PW :: " + String.valueOf(password)
});
// ===============================================================
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// [퍼미션 권한 체크 실시]
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
// [퍼미션이 부여되어있지 않은 경우 종료]
M_LOG[0] = "[ERROR] : Permission Not Granted";
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(M_LOG[0]));
subscriber.onComplete();
}
} else {
// [인풋 데이터 널 체크] : [비밀 번호는 없을 수 있으니 방어 로직 제외]
if (C_Util.stringNotNull(ssid) == true){
// [와이파이가 정상적으로 활성화 상태 인 지 확인]
if (C_StateCheck.getWifiEnable(mContext) == true){
// TODO [연결 하려는 SSID 와 , 현재 연결 된 WIFI SSID 가 동일한 지 확인]
String nowWifiSsid = "";
WifiManager wifimanager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
String connectIp = "";
try {
WifiInfo wifiInfo = wifimanager.getConnectionInfo();
nowWifiSsid = wifiInfo.getSSID();
nowWifiSsid = nowWifiSsid.replaceAll("[\"]", "");
nowWifiSsid = nowWifiSsid.trim();
}
catch (Exception es){}
if (ssid.trim().equals(nowWifiSsid) == true){
WifiInfo wifiInfo = wifimanager.getConnectionInfo();
DhcpInfo dhcpInfo = wifimanager.getDhcpInfo();
int wIp = dhcpInfo.ipAddress;
connectIp = String.format("%d.%d.%d.%d", (wIp & 0xff), (wIp >> 8 & 0xff), (wIp >> 16 & 0xff), (wIp >> 24 & 0xff));
M_LOG[0] = "[SUCCESS] : Wifi Ssid Equals";
S_Log._W_(ACTIVITY_NAME + " : M_LOG : " + String.valueOf(M_LOG[0]), new String[]{
"getIpAddress :: " + String.valueOf(connectIp)
});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext(String.valueOf(connectIp));
subscriber.onComplete();
}
}
else {
// TODO [안드로이드 버전 분기 처리 수행]
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { // [상위 버전]
// --------------------------------------------
// TODO [WifiNetworkSpecifier] : Wi-Fi 네트워크를 요청하는 데 사용되는 네트워크 지정자 객체
// --------------------------------------------
// TODO [와이파이] : 설정 화면에서 연결 된 적이 없어도 AP 연결 및 IP 획득 >> 서버 소켓 활성 수행
// --------------------------------------------
WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
.setSsid(String.valueOf(ssid))
.setWpa2Passphrase(String.valueOf(password)) // TODO [WPA2 형식]
.build();
// --------------------------------------------
// TODO [WifiNetworkSpecifier] : 와이파이 정보 입력
// --------------------------------------------
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wifiNetworkSpecifier)
.build();
ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.requestNetwork(networkRequest, new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
S_Log._W_(ACTIVITY_NAME + " :: requestNetwork :: onAvailable :: Wifi Connection Success", null);
// [와이파이 정보 확인]
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkCapabilities netCaps = cm.getNetworkCapabilities(network);
WifiInfo wifiInfo = (WifiInfo) netCaps.getTransportInfo();
int wIp = wifiInfo.getIpAddress();
String getIpAddress = String.format("%d.%d.%d.%d", (wIp & 0xff), (wIp >> 8 & 0xff), (wIp >> 16 & 0xff), (wIp >> 24 & 0xff));
// [로그 출력]
S_Log._W_(ACTIVITY_NAME + " :: requestNetwork :: onAvailable :: IP 정보 출력 실시", new String[]{
"getIpAddress :: " + String.valueOf(getIpAddress)
});
// [콜백 해제] : [AP 연결 종료]
//try { connectivityManager.unregisterNetworkCallback(this); } catch (Exception e){ e.printStackTrace(); }
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext(String.valueOf(getIpAddress));
subscriber.onComplete();
}
}
@Override
public void onUnavailable() {
super.onUnavailable();
S_Log._E_(ACTIVITY_NAME + " :: requestNetwork :: onUnavailable :: Wifi Connection Fail", null);
// [콜백 해제] : [AP 연결 종료]
try { connectivityManager.unregisterNetworkCallback(this); } catch (Exception e){ e.printStackTrace(); }
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false) {
subscriber.onNext("");
subscriber.onComplete();
}
}
@Override
public void onLost(Network network) {
super.onLost(network);
S_Log._E_(ACTIVITY_NAME + " :: requestNetwork :: onLost :: Wifi Connection Lost", null);
// [콜백 해제] : [AP 연결 종료]
try { connectivityManager.unregisterNetworkCallback(this); } catch (Exception e){ e.printStackTrace(); }
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext("");
subscriber.onComplete();
}
}
});
}
else { // [하위 버전]
// TODO [WifiConfiguration : 와이파이 연결 옵션 설정 수행]
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "\"" + String.valueOf(ssid) + "\""; // [연결하고자 하는 SSID]
wifiConfiguration.status = WifiConfiguration.Status.DISABLED;
wifiConfiguration.priority = 40;
// TODO [WPA, WPA2 옵션] : [와이파이 연결 수행]
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wifiConfiguration.preSharedKey = "\"".concat(String.valueOf(password)).concat("\""); // [비밀 번호]
// TODO [OPEN 옵션] : [와이파이 연결 수행]
/*
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wifiConfiguration.allowedAuthAlgorithms.clear();
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
// */
// TODO [WEB 옵션] : [와이파이 연결 수행]
/*
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wifiConfiguration.wepKeys[0]="\"".concat(String.valueOf(password)).concat("\"");
wifiConfiguration.wepTxKeyIndex=0;
// */
WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) {
wifiManager.setWifiEnabled(true);
}
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
// TODO [연결 추가]
int wifiId = wifiManager.addNetwork(wifiConfiguration);
// TODO [연결 상태 확인]
if (wifiId != -1) {
wifiManager.enableNetwork(wifiId, true);
WifiInfo wifiInfo = wifimanager.getConnectionInfo();
DhcpInfo dhcpInfo = wifimanager.getDhcpInfo();
int wIp = dhcpInfo.ipAddress;
String getIpAddress = String.format("%d.%d.%d.%d", (wIp & 0xff), (wIp >> 8 & 0xff), (wIp >> 16 & 0xff), (wIp >> 24 & 0xff));
S_Log._W_(ACTIVITY_NAME + " :: WifiConfiguration :: Connection Wifi", new String[]{
"getIpAddress :: " + String.valueOf(getIpAddress)
});
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext(String.valueOf(getIpAddress));
subscriber.onComplete();
}
}
else {
S_Log._E_(ACTIVITY_NAME + " :: WifiConfiguration :: Connection Fail", null);
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onNext("");
subscriber.onComplete();
}
}
}
}
}
else {
M_LOG[0] = "[ERROR] : Wifi Enabled False";
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(M_LOG[0]));
subscriber.onComplete();
}
}
}
else {
M_LOG[0] = "[ERROR] : Input Ssid Is Null";
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(M_LOG[0]));
subscriber.onComplete();
}
}
}
}
}, 0);
} catch (final Exception e){
S_Log._printStackTrace_(mContext, S_FinalData.LOG_BUG_STATE, null, e);
// ------------------------------------------------------
// TODO [리턴 데이터 반환]
// ------------------------------------------------------
try {
M_LOG[0] = "[EXCEPTION] : " + String.valueOf(e.getMessage());
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(M_LOG[0]));
subscriber.onComplete();
}
}
catch (Exception ex){
ex.printStackTrace();
}
}
});
}
// ------------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : observableWifiInfo : 현재 연결 된 와이파이 정보 확인
// ------------------------------------------------------------------------------------------
// TODO [호출 방법 소스 코드]
// -----------------------------------------------------------------------------------------
/*
try {
C_Wifi_Ap_Module.observableWifiInfo(A_Intro.this)
.subscribeOn(AndroidSchedulers.mainThread()) // [Observable (생성자) 로직을 IO 스레드에서 실행 : 백그라운드]
.observeOn(Schedulers.io()) // [Observer (관찰자) 로직을 메인 스레드에서 실행]
.subscribe(new Observer<Map<String, String>>() { // [Observable.create 타입 지정]
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull Map<String, String> value) {
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
S_Log._printStackTrace_(mContext, S_FinalData.LOG_BUG_STATE, null, e);
}
*/
// -----------------------------------------------------------------------------------------
public static Observable<Map<String, String>> observableWifiInfo(Context mContext) {
// [로직 처리 실시]
return Observable.create(subscriber -> {
try {
// ===============================================================
S_Log._D_(ACTIVITY_NAME + " :: 현재 연결 된 와이파이 정보 확인 실시", null);
// ===============================================================
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// [퍼미션 권한 체크 실시]
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
// [퍼미션이 부여되어있지 않은 경우 종료]
String errorMsg = "[ERROR] : Wifi Permission not Granted (와이파이 기능 확인에 필요한 권한을 확인해주세요. : GPS , Location)";
// ===============================================================
S_Log._E_("ERROR", new String[]{
"ERROR :: " + String.valueOf(errorMsg)
});
// ===============================================================
// [리턴 반환 실시]
subscriber.onError(new Throwable(errorMsg));
subscriber.onComplete();
} else {
// ---------------------------------------------------------------
// TODO [현재 와이파이 연결된 상태 체크]
// ---------------------------------------------------------------
if (C_StateCheck.isWifiConnected(mContext) == true) {
// [Android 12 이상 분기 처리]
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
//*
// [ConnectivityManager 생성]
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
// [와이파이 정보 확인]
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
}
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities net) {
// [와이파이 정보 확인]
WifiInfo wifiInfo = (WifiInfo) net.getTransportInfo();
String getSsid = String.valueOf(wifiInfo.getSSID().replaceAll("[\"]", ""));
int wIp = wifiInfo.getIpAddress();
String getIpAddress = String.format("%d.%d.%d.%d", (wIp & 0xff), (wIp >> 8 & 0xff), (wIp >> 16 & 0xff), (wIp >> 24 & 0xff));
String getBSSID = String.valueOf(wifiInfo.getBSSID().trim());
// [로그 출력]
// ===============================================================
S_Log._D_(ACTIVITY_NAME + " :: [HIGHT] 현재 연결된 와이파이 정보 출력 실시", new String[]{
"getSsid :: " + String.valueOf(getSsid),
"getIpAddress :: " + String.valueOf(getIpAddress),
"getBSSID :: " + String.valueOf(getBSSID)
});
// ===============================================================
// TODO [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
Map<String, String> returnData = new HashMap<>();
returnData.put("SSID", String.valueOf(getSsid));
returnData.put("BSSID", String.valueOf(getBSSID));
returnData.put("IP", String.valueOf(getIpAddress));
subscriber.onNext(returnData);
subscriber.onComplete();
}
}
};
cm.requestNetwork(networkRequest, networkCallback);
// */
} else {
// [와이파이 정보 확인]
WifiManager wifimanager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifimanager.getConnectionInfo();
DhcpInfo dhcpInfo = wifimanager.getDhcpInfo();
int wIp = dhcpInfo.ipAddress;
String getSsid = wifiInfo.getSSID();
getSsid = getSsid.replaceAll("[\"]", "");
String getIpAddress = String.format("%d.%d.%d.%d", (wIp & 0xff), (wIp >> 8 & 0xff), (wIp >> 16 & 0xff), (wIp >> 24 & 0xff));
String getBSSID = wifiInfo.getBSSID();
getBSSID = getBSSID.trim();
// [로그 출력]
// ===============================================================
S_Log._D_(ACTIVITY_NAME + " :: [LOW] 현재 연결된 와이파이 정보 출력 실시", new String[]{
"getSsid :: " + String.valueOf(getSsid),
"getIpAddress :: " + String.valueOf(getIpAddress),
"getBSSID :: " + String.valueOf(getBSSID)
});
// ===============================================================
// TODO [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
Map<String, String> returnData = new HashMap<>();
returnData.put("SSID", String.valueOf(getSsid));
returnData.put("BSSID", String.valueOf(getBSSID));
returnData.put("IP", String.valueOf(getIpAddress));
subscriber.onNext(returnData);
subscriber.onComplete();
}
}
}
else {
// [에러 메시지 삽입]
String errorMsg = "[ERROR] : Wifi Connected False Status";
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(errorMsg));
subscriber.onComplete();
}
}
}
}
}, 0);
} catch (final Exception e){
S_Log._printStackTrace_(mContext, S_FinalData.LOG_BUG_STATE, null, e);
// ===============================================================
S_Log._E_(ACTIVITY_NAME + " :: 와이파이 정보 확인 에러 발생", new String[]{
"EXCEPTION :: " + String.valueOf(e.getMessage())
});
// ===============================================================
// ------------------------------------------------------
// TODO [리턴 데이터 반환]
// ------------------------------------------------------
try {
// [에러 메시지 삽입]
String errorMsg = "[EXCEPTION] : " + String.valueOf(e.getMessage());
// [리턴 반환 실시]
if (subscriber != null && subscriber.isDisposed() == false){
subscriber.onError(new Throwable(errorMsg));
subscriber.onComplete();
}
}
catch (Exception ex){
ex.printStackTrace();
}
}
});
}
// ------------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : getWifiRssiMsg : 와이파이 RSSI 신호 강도 세기 메시지 확인
// ------------------------------------------------------------------------------------------
public static String getWifiRssiMsg(int level) {
/**
* // -----------------------------------------
* [getWifiRssiMsg 메소드 설명]
* // -----------------------------------------
* 1. 와이파이 Rssi 값 신호 세기 확인 메시지
* // -----------------------------------------
* 2. 호출 방식 : C_Wifi_Ap_Module.getWifiRssiMsg(-40);
* // -----------------------------------------
* */
// [리턴 변수 선언]
String returnData = "";
// [로직 처리 수행]
try {
if(level >= -39) {
returnData = "신호강도 : 매우좋음 (RSSI : " + String.valueOf(level) + ")";
}
else if(level >= -49 && level <= -40) {
returnData = "신호강도 : 좋음 (RSSI : " + String.valueOf(level) + ")";
}
else if(level >= -64 && level <= -50) {
returnData = "신호강도 : 보통 (RSSI : " + String.valueOf(level) + ")";
}
else {
returnData = "신호강도 : 나쁨 (RSSI :" + String.valueOf(level) + ")";
}
}
catch (Exception e){
e.printStackTrace();
returnData = "[Exception] : " + String.valueOf(e.getMessage());
}
// [리턴 반환]
return returnData;
}
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : getWifiPasswordMsg : 와이파이 비밀번호 설정 여부 메시지 포맷 출력
// -----------------------------------------------------------------------------------------
public static String getWifiPasswordMsg(String capabilities) {
/**
* // -----------------------------------------
* [getWifiPasswordMsg 메소드 설명]
* // -----------------------------------------
* 1. 와이파이 비밀번호 인증 필요 메시지 확인
*
* Capability 문자열의 구성 : [프로토콜-인증방식-암호알고리즘+추가암호알고리즘]
* // -----------------------------------------
* 2. 호출 방식 :
*
* C_Wifi_Ap_Module.getWifiPasswordMsg("[WPA2-PSK-CCMP][RSN-PSK-CCMP][ESS]");
* C_Wifi_Ap_Module.getWifiPasswordMsg("[RSN-SAE-CCMP][ESS][MFPR][MFPC]");
* C_Wifi_Ap_Module.getWifiPasswordMsg("[WPA2-PSK-CCMP][RSN-PSK-CCMP][ESS][WPS]");
* C_Wifi_Ap_Module.getWifiPasswordMsg("[ESS][WPS]");
* // -----------------------------------------
* 3. 참고 내용 :
*
* WiFi 보안 프로토콜 : WEP -> WPA -> WPA2 로 발전
* WiFi 인증 방법 : 개인용: WPA-Private (PSK (Pre-Shared-Key)) / 기업용: WPA-Enterprise (EAP - RADIUS 인증서버 요구)
* // -----------------------------------------
* */
// [리턴 변수 선언]
String returnData = "";
// [로직 처리 수행]
try {
if (C_Util.stringNotNull(capabilities) == true){
String upperString = String.valueOf(capabilities).toUpperCase();
if (upperString.contains("PSK") || upperString.contains("EAP") || upperString.contains("SAE")){
// -------------------------------------------------
// TODO [PSK] : 개인 모드 : 사전에 정해 진 인증 키 필요
// -------------------------------------------------
// TODO [EAP] : 엔터 프라이즈 모드 : 별도 인증 시스템 연동 및 아이디, 비밀번호 입력 필요
// -------------------------------------------------
// TODO [SAE] : WPA3 에서 PSK 를 SAE 로 대체 >> 재생 취약점 방지
// -------------------------------------------------
returnData = "[Auth] : 인증 필요";
}
else {
returnData = "[Open] : 공개 활성";
}
}
else {
returnData = "[Error] : Input Data Is Null";
}
}
catch (Exception e){
e.printStackTrace();
returnData = "[Exception] : " + String.valueOf(e.getMessage());
}
// [리턴 반환]
return returnData;
}
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : getWifiCreateQrData : 와이파이 연결에 필요한 QR 코드 생성 데이터 포맷
// -----------------------------------------------------------------------------------------
public static String getWifiCreateQrData(String ssid, String pw, String auth) {
/**
* // -----------------------------------------
* [getWifiCreateQrData 메소드 설명]
* // -----------------------------------------
* 1. 와이파이 연결에 필요한 QR 코드 생성 데이터 포맷
* // -----------------------------------------
* 2. 호출 방식 :
*
* C_Wifi_Ap_Module.getWifiCreateQrData("TWOK", "T0123456789", "WPA");
* C_Wifi_Ap_Module.getWifiCreateQrData("TWOK", "T0123456789", "WEP");
* C_Wifi_Ap_Module.getWifiCreateQrData("TWOK", "", "");
* // -----------------------------------------
* 3. 참고 :
*
* WIFI:S:TWOK;T:WPA;P:T0123456789;; ----- [WPA/WPA2 암호화]
*
* WIFI:S:TWOK;T:WEP;P:T0123456789;; ----- [WEP 암호화]
*
* WIFI:S:TWOK;T:nopass;; ----- [암호화 없음]
* // -----------------------------------------
* */
// [리턴 변수 선언]
String returnData = "";
// [로직 처리 수행]
try {
if (C_Util.stringNotNull(ssid) == true){ // [SSID 널 아님]
returnData += "WIFI:";
returnData += "S:" + String.valueOf(ssid)+";";
if (C_Util.stringNotNull(auth) == true){ // [타입 널 아님]
returnData += "T:" + String.valueOf(auth)+";";
returnData += "P:" + String.valueOf(pw)+";;";
}
else { // [타입 널 임]
returnData += "T:nopass" + ";;";
}
}
}
catch (Exception e){
e.printStackTrace();
}
// [리턴 반환]
return returnData;
}
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : getWifiGHz : 와이파이 GHZ 및 채널 확인
// -----------------------------------------------------------------------------------------
public static String getWifiGHz(int frequency) {
/**
* // -----------------------------------------
* [getWifiGHz 메소드 설명]
* // -----------------------------------------
* 1. 와이파이 GHZ 및 채널 확인
* // -----------------------------------------
* 2. 호출 방식 :
*
* C_Wifi_Ap_Module.getWifiGHz(2437);
*
* C_Wifi_Ap_Module.getWifiGHz(5180);
*
* // -----------------------------------------
* 3. 리턴 데이터 : 2.4 / 5 GHZ
* // -----------------------------------------
* */
// [리턴 변수 선언]
String returnData = "";
boolean errorFlag = false;
String m_log = "";
try {
// [음수값 제외 방어 로직]
if (frequency < 0){
errorFlag = true;
m_log = "[ERROR] : Input Data Negative Number";
}
// [인풋 값이 특정 범위를 만족하는지 확인]
if (frequency < 2000 || frequency > 6000){
errorFlag = true;
m_log = "[ERROR] : Input Data Range";
}
// [로직 처리 실시]
if (errorFlag == false){
// [frequency 사용해 채널 계산]
int channel = -1;
if(frequency >= 2412 && frequency <= 2484) {
if (frequency == 2484){
channel = (frequency-2412) /5;
}
channel = (frequency-2412) /5 + 1;
}else if( frequency >= 5170 && frequency <= 5825) {
channel = (frequency-5170) /5 + 34;
}
else {
channel = -1;
}
// [채널 범위 확인해서 GHZ 계산]
if (channel < 0){
errorFlag = true;
m_log = "[ERROR] : Input Data Negative Number";
}
else {
m_log = "[SUCCESS] : (GHZ) Check Success";
// [채널 범위 확인해서 GHZ 계산]
if (channel < 15){
/**
* ----------------------------------
* [상세 내역]
* ----------------------------------
* (채널 = 1 / 주파수 = 2412)
* (채널 = 2 / 주파수 = 2417)
* (채널 = 3 / 주파수 = 2422)
* (채널 = 4 / 주파수 = 2427)
* (채널 = 5 / 주파수 = 2432)
* (채널 = 6 / 주파수 = 2437)
* (채널 = 7 / 주파수 = 2442)
* (채널 = 8 / 주파수 = 2447)
* (채널 = 9 / 주파수 = 2452)
* (채널 = 10 / 주파수 = 2457)
* (채널 = 11 / 주파수 = 2462)
* (채널 = 12 / 주파수 = 2467)
* (채널 = 13 / 주파수 = 2472)
* (채널 = 14 / 주파수 = 2484)
* ----------------------------------
* */
returnData = "2.4GHz";
}
else {
/**
* ----------------------------------
* [상세 내역]
* ----------------------------------
* U-NII (Low) :
*
* (채널 = 36 / 주파수 = 5180)
* (채널 = 40 / 주파수 = 5200)
* (채널 = 44 / 주파수 = 5220)
* (채널 = 48 / 주파수 = 5240)
* ----------------------------------
* U-NII (Mid) :
*
* (채널 = 52 / 주파수 = 5260)
* (채널 = 56 / 주파수 = 5280)
* (채널 = 60 / 주파수 = 5300)
* (채널 = 64 / 주파수 = 5320)
* ----------------------------------
* U-NII (High) :
*
* (채널 = 149 / 주파수 = 5745)
* (채널 = 153 / 주파수 = 5765)
* (채널 = 157 / 주파수 = 5785)
* (채널 = 161 / 주파수 = 5805)
* ----------------------------------
* - (채널 = 165 / 주파수 = 5825)
* ----------------------------------
* U-NII (Extended) :
*
* (채널 = 100 / 주파수 = 5500)
* (채널 = 104 / 주파수 = 5520)
* (채널 = 108 / 주파수 = 5540)
* (채널 = 112 / 주파수 = 5560)
* (채널 = 116 / 주파수 = 5580)
* (채널 = 120 / 주파수 = 5600)
* (채널 = 124 / 주파수 = 5620)
* (채널 = 128 / 주파수 = 5640)
* (채널 = 132 / 주파수 = 5660)
* (채널 = 136 / 주파수 = 5680)
* (채널 = 140 / 주파수 = 5700)
* ----------------------------------
* */
returnData = "5GHz";
}
}
}
} catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
m_log = "[EXCEPTION] : " + String.valueOf(e.getMessage());
}
// [로그 출력 실시]
//*
// ===============================================================
S_Log._D_("와이파이 GHZ 및 채널 확인 실시", new String[]{
"INPUT :: " + String.valueOf(frequency),
"M_LOG :: " + String.valueOf(m_log),
"RETURN :: " + String.valueOf(returnData)
});
// ===============================================================
// */
// [리턴 반환 실시]
return returnData;
}
} // TODO [클래스 종료]
반응형
'투케이2K 유틸파일' 카테고리의 다른 글
Comments