login history를 따로 작업해야하는 일이 생겼다.
원래는 서버에서 ip가져오는 작업을 해서 처리하려했으나 네트워크, 서버 구조상 계속 내부주소가 찍히는 문제가 발생했다.^^
그렇게 나의 3일 방황기가 시작되었따...
android에서 ip가져오는 건 단 한번의 검색으로 쉽게 작업했다.
스택오버플로에서 따온 코드를 살짝 수정만으로도 잘나와서 잘못된 코드인줄도 몰랐다.
아 잘못된 코드는 아니지 목적에 맞지않는 코드였을 뿐.
public ip를 가져와야하는데 로그를 찍으면 로컬네트워크로 찍힌다. 로컬네트워크라는 것도 ipv6을 ipv4로 변환해보고나서야 알았다.(ipv6 -> ipv4로 변환은 주소체계가 달라서 안될 수도 있다.)
아래는 그에 대한 코드이다. (주의! 로컬네트워크 주소가져오는 코드임)
public class IPAddressUtil {
public String getIPAddress(Context context) {
String ip = null;
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm != null) {
Network network = cm.getActiveNetwork();
if (network != null) {
NetworkCapabilities nc = cm.getNetworkCapabilities(network);
if (nc != null) {
if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
ip = getWifiIPAddress(context);
} else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
ip = getMobileIPAddress();
}
}
}
}
return ip;
}
private String getWifiIPAddress(Context context) {
WifiManager wm = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wm != null) {
int ip = wm.getConnectionInfo().getIpAddress();
return String.format(
"%d.%d.%d.%d",
(ip & 0xff),
(ip >> 8 & 0xff),
(ip >> 16 & 0xff),
(ip >> 24 & 0xff)
);
}
return null;
}
private String getMobileIPAddress() {
try {
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface intf : interfaces) {
List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
for (InetAddress addr : addrs) {
if (!addr.isLoopbackAddress()) {
String sAddr = addr.getHostAddress();
boolean isIPv4 = sAddr.indexOf(':') < 0;
if (isIPv4) {
return sAddr; // IPv4 주소 반환
} else {
// IPv6 주소의 Zone ID 제거
int zoneIndex = sAddr.indexOf('%');
if (zoneIndex > 0) {
sAddr = sAddr.substring(0, zoneIndex);
}
if (!sAddr.startsWith("fe80::")) {
return sAddr; // 유효한 IPv6 주소 반환
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
그래서 검색하다가 나온 ipify-android
https://github.com/chintan369/Ipify-Android
GitHub - chintan369/Ipify-Android: Ipify allows users to get current public IP address for connected network in real-time
Ipify allows users to get current public IP address for connected network in real-time - chintan369/Ipify-Android
github.com
이 라이브러리 좋으다.
다만 Java프로젝트에서 사용하려면 아래와 같이 추가해주자.
// build.gradle (Project)
plugins {
...
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}
// build.gradle (App)
plugins {
...
id 'kotlin-android'
}
implementation 'com.github.chintan369:Ipify-Android:1.0.1'
//클래스
Ipfy.Companion.init(this.context, IpfyClass.UniversalIP);
Ipfy.Companion.getInstance1().getPublicIpObserver().observe(this, ipAddressData -> {
ip = ipAddressData.getCurrentIpAddress();
});
하지만 이 또한 문제가 있었는데 ipv4 주소는 가져오지 못하는 것이였다.
우리는 1번으로 ipv4 주소 저장이고 null값일 때 ipv6를 저장하는 것이 목표였기때문에
코드에 단 몇줄만 추가하면되는 저 간단한 라이브러리를 사용할 수 없었다. =_=....
최종으로 사용한 코드는 바로 이것이다.
public class PublicIPThread {
public void execute() {
Thread thread = new Thread(() -> {
try {
String ipAddress = fetchIPAddress("https://api4.my-ip.io/v2/ip.txt");
if (ipAddress == null || ipAddress.isEmpty()) {
ipAddress = fetchIPAddress("https://api.my-ip.io/v2/ip.txt");
}
if (ipAddress != null && !ipAddress.isEmpty()) {
Logger.d(ipAddress);
} else {
mainActivity.ip = "";
Logger.e("IP is empty");
}
} catch (Exception e) {
e.printStackTrace();
}
});
thread.start();
}
private String fetchIPAddress(String urlString) throws IOException {
try (Scanner scnr = new Scanner(new URL(urlString).openStream(), "UTF-8").useDelimiter("\\A")) {
if (scnr.hasNext()) {
return scnr.nextLine();
} else {
return null;
}
}
}
}
그래도 간략한 편이다.
이번에 ip가져오는 로직을 짜면서 공부한 것인데
모바일에서 lte일 때 가져온 ip로는 현재 사용자의 위치를 표기하지 못한다.
대부분 이동통신사 위치를 가르킨다. (그래도 통신사 내부에 기록이 남는다고 한다)
또 현재 내 아이피는 구글에 쳐보거나 whatismyipaddress라는 페이지에 가도 알 수 있지만
삼성 휴대폰이라면 히든메뉴를 통해 알 수도 있다. (https://m.blog.naver.com/superjini75/222075645718)
참고
https://github.com/chintan369/Ipify-Android
https://namu.wiki/w/%ED%86%B5%EC%8B%A0%EC%82%AC%20IP
'Android' 카테고리의 다른 글
[Flutter] 설치 (0) | 2025.04.22 |
---|