Android 获取ip地点多种方式介绍

种地  金牌会员 | 2024-10-23 20:57:33 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 878|帖子 878|积分 2634

Android 获取ip地点多种方式


  
一、前言

adb shell 的 ifconfig可以获取当前装备网络节点信息;
这些信息利用Android代码也是可以获取的;
Android 获取网络ip有多种方式,有时间某种方式获取失败的情况下;
那么就可以换一种获取方式,全部多学习一下获取网络ip相干信息是有用的。
本文介绍三种获取网络ip信息的方式,并且末了一种的代码不用任何权限就能获取到相干节点的ip和MAC地点,有爱好的可以看看。
二、获取ip地点

1、adb shell ifconfig

  1. console:/ # ifconfig                                                           
  2. wlan0     Link encap:Ethernet  HWaddr 38:64:07:88:6a:f6  Driver usb
  3.           UP BROADCAST MULTICAST  MTU:1500  Metric:1
  4.           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  5.           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  6.           collisions:0 txqueuelen:3000
  7.           RX bytes:0 TX bytes:0
  8. 。。。
  9. ap0       Link encap:Ethernet  HWaddr 3e:ea:29:0a:07:d9
  10.           inet addr:192.168.43.1  Bcast:192.168.43.255  Mask:255.255.255.0
  11.           inet6 addr: fe80::3cea:29ff:fe0a:7d9/64 Scope: Link
  12.           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
  13.           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  14.           TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
  15.           collisions:0 txqueuelen:1000
  16.           RX bytes:0 TX bytes:1450
复制代码
一般情况热门的节点名称都是ap0,可以看到ip地点和相干信息。
上面的wifi未连接所以才没有ip地点,如果有有线网ip也会表现。
一般情况下网络对应节点名称:
  1. wifi节点:wlan0,
  2. 热点:ap0/wlan1,
  3. 有线网:eth0/eth1
  4. 投屏节点:p2p
复制代码
2、Android 代码获连接的wifi 的 ip地点:

  1. public static String getWifiIpAddress(Context context) {
  2.         WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
  3.         
  4.         if (!wifiManager.isWifiEnabled()) {
  5.             // Wi-Fi is not enabled, return null or handle the case accordingly
  6.             return null;
  7.         }
  8.         
  9.         int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
  10.         byte[] bytes = new byte[4];
  11.         for (int i = 0; i < 4; ++i) {
  12.             bytes[i] = (byte)(ipAddress >> ((3 - i) * 8));
  13.         }
  14.         
  15.         StringBuilder sb = new StringBuilder();
  16.         for (byte b : bytes) {
  17.             sb.append((b & 0xFF)).append(".");
  18.         }
  19.         sb.deleteCharAt(sb.length() - 1);
  20.         
  21.         return sb.toString();
  22.     }
复制代码
要调用这段代码并获得Wifi的 IP 地点,只需传入一个有效的 Context 对象作为参数即可。
当然获取wifi网络另有其他方法,可以继续往下看看。
3、获取有线网的ip

  1.     //获取有线网的ip地址
  2.     public static String getEthernetIpAddress(Context context) {
  3.         LogUtil.debugInform("");
  4.         final Network network = getFirstEthernet(context);
  5.         if (network == null) {
  6.             return "";
  7.         }
  8.         ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  9.         final LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
  10.         if (linkProperties != null) {
  11.             for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
  12.                 InetAddress inetAddress = linkAddress.getAddress();
  13.                 if (inetAddress instanceof Inet4Address) {
  14.                     return inetAddress.getHostAddress();
  15.                 }
  16.             }
  17.         }
  18.         return "";
  19.     }
  20.     private static Network getFirstEthernet(Context context) {
  21.         ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  22.         final Network[] networks = connectivityManager.getAllNetworks();
  23.         for (final Network network : networks) {
  24.             NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
  25.             //关键:判断网络类型 有线网
  26.             if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
  27.                 return network;
  28.             }
  29.         }
  30.         return null;
  31.     }
复制代码
利用这个方法也可以获取wifi的ip地点;修改成wifi类型判断就行了。
利用这个方法必须保证已经连接上了这个网才气查到对应的类型的ip。
网络类型定义:
package\modules\Connectivity\framework\src\android\net\ConnectivityManager.java
  1.     public static final int TYPE_MOBILE      = 0; //SIM卡 网络
  2.     public static final int TYPE_WIFI        = 1; //wifi 网络
  3.     public static final int TYPE_MOBILE_MMS  = 2;
  4.     public static final int TYPE_MOBILE_SUPL = 3;
  5.     public static final int TYPE_MOBILE_DUN  = 4;
  6.     public static final int TYPE_MOBILE_HIPRI = 5;
  7.     public static final int TYPE_WIMAX       = 6;
  8.     public static final int TYPE_BLUETOOTH   = 7;
  9.     public static final int TYPE_DUMMY       = 8;
  10.     public static final int TYPE_ETHERNET    = 9;//有线网网络
复制代码
4、Android 代码获取全部网络节点的ip地点和MAC地点:

热门没有相干暴露获取的api;
Android 热门ip地点 IpServer 和相干的类都是隐蔽的所以无法上Wifi那样通过api获取到ip地点;
但是可以通过遍历节点的数据,获取到ip地点,
wifi、有线网、热门的ip地点和节点相干的信息都可以如许获取到:
  1.     /**
  2.      * 获取ip地址,key为网络端口名称,比如wlan0、eth0、ap0等,value为ip地址,以及节点相关的MAC地址
  3.      *
  4.      * @return 键值对
  5.      */
  6.     private HashMap<String, String> getNetIPs() {
  7.         HashMap<String, String> hashMap = new HashMap<>();
  8.         try {
  9.             for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
  10.                 NetworkInterface intf = en.nextElement(); //打印的信息和 ifconfig 的大致对应
  11.                 Log.i(TAG, "----》getEtherNetIP inf = " + intf); //eth0、wifi...
  12.                 for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
  13.                     InetAddress inetAddress = enumIpAddr.nextElement();
  14.                     if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
  15.                         Log.i(TAG, "----》getEtherNetIP intf.getName() = " + intf.getName());
  16.                         Log.i(TAG, "----》getEtherNetIP inetAddress = " + inetAddress);
  17.                         Log.i(TAG, "----》getEtherNetIP inetAddress  getHostAddress = " + inetAddress.getHostAddress());
  18.                         byte[] hardwareAddress = intf.getHardwareAddress();
  19.                                                
  20.                         //节点对应的ip地址
  21.                         hashMap.put(intf.getName(), "" + inetAddress.getHostAddress());
  22.                         //节点对应的MAC地址,mac地址是byte数值数据,要转换成字符串
  23.                         String mac = bytesToString(hardwareAddress);
  24.                         hashMap.put(intf.getName() + "-MAC", "" + mac);
  25.                     }
  26.                 }
  27.             }
  28.         } catch (SocketException ex) {
  29.             Log.e(TAG, "getEtherNetIP = " + ex.toString());
  30.         }
  31.         return hashMap;
  32.     }
  33.    
  34.     //字节数据转换成字符串
  35.     public static String bytesToString(byte[] bytes) {
  36.         if (bytes == null || bytes.length == 0) {
  37.             return null;
  38.         }
  39.         StringBuilder buf = new StringBuilder();
  40.         for (byte b : bytes) {
  41.             buf.append(String.format("%02X:", b));
  42.         }
  43.         if (buf.length() > 0) {
  44.             buf.deleteCharAt(buf.length() - 1);
  45.         }
  46.         return buf.toString();
  47.     }
复制代码
所以下面这个方法对于很多场景都是可用的。
上面方法在节点名称保存了ip地点和对应的MAC地点;
可以根据需求进行适当修改处理。
上面是获取了ifconfig信息 节点上 Inet4Address 类型的全部信息。
如果只要获取热门的ip地点,可以如许写:
Android 代码获取热门的 ip地点:

主要代码:
  1.     /**
  2.      * 获取热点ip地址字符串
  3.      */
  4.     private String getHotspottIPs() {
  5.         try {
  6.             for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
  7.                 NetworkInterface intf = en.nextElement(); //打印的信息和 ifconfig 的大致对应
  8.                 Log.i(TAG, "----》getEtherNetIP inf = " + intf); //eth0、wifi...
  9.                 for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
  10.                     InetAddress inetAddress = enumIpAddr.nextElement();
  11.                     if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address && "ap0".equals(intf.getName())) { //判断热点的节点名称ap0,如果不是ap0,就自己修改
  12.                          return "" + inetAddress.getHostAddress();
  13.                     }
  14.                 }
  15.             }
  16.         } catch (SocketException ex) {
  17.             Log.e(TAG, "getEtherNetIP = " + ex.toString());
  18.         }
  19.         return "";
  20.     }
  21.    
复制代码
上面的获取热门ip的方法,是不用Context对象,不用权限,
平凡应用就能调用和获取到信息,验证过是ok的。
所以WiFi、有线网这些网络的ip地点也可以参考如许获取;
需要知道当前体系网络的节点的具体情况,热门节点不一定用ap0,也有的体系利用wlan1的。
三、其他

1、ip地点获取小结

adb shell ifconfig 可以看到当前装备网络节点情况。
获取网络ip的方式有几种:
  1. 1、获取wifi 的ip
  2. 可以通过 WifiManager 获取当前连接的wifi信息,获取到ip地址;
  3. 2、获取有线网、wifi的ip
  4. 通过获取 ConnectivityManager获取连接的网络 Network-->LinkProperties获取到ip地址。
  5. 3、获取有线网、wifi、热点、p2p的ip
  6. 通过获取所有节点信息:NetworkInterface.getNetworkInterfaces() 获取对应的ip地址和MAC地址。
复制代码
前面两种方式都是需要相应权限的,第二种估计要体系签名才可以获取到;
只有第三种不需要任何权限,平凡应用就可以获取到;
但是第一和第二种方式是不需要知道节点名称的,第三种是需要知道节点名称的;
所以如果有体系权限,第一和第二种方式,对于全部平台方案都是可用的;
第三种方案可能对于差别平台方案要进行适配;
因为差别平台的热门和有线网等网络的节点可能差别,但是大部门都是雷同的。
第三种方式是信息量最多的。
2、热门开启流程

体系源码追踪:
  1. 1、ConnectivityManager.startTethering
  2. 2、TetheringManager.startTethering
  3. 3、TetheringService.TetheringConnector.startTethering
  4. 4、Tethering.startTethering(request, listener);
  5. 5、WifiManager.startTetheredHotspot(null /* use existing softap config */)
  6. 6、WifiServiceImpl.startTetheredHotspot(@Nullable SoftApConfiguration softApConfig)
  7. 7、ActiveModeWarden.startSoftAp(apModeConfig);
  8. 8、ActiveModeManager.start();
  9. 10、WifiNative.startSoftAp
  10. 11、HostapdHal.addAccessPoint
复制代码
热门开启流程原文链接:
https://blog.csdn.net/wenzhi20102321/article/details/128473734

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表