Android开启热点后作为路由器,获取AP端IP地址

最近在做类似面对面通信,需要一台手机作为AP端开启热点,另一台手机作为STA端连接热点,然后AP端告诉STA端它的IP地址,进行socket通信。
手机在联网时,就会被分配一个IP地址,它在开启热点时,它本身作为一个“路由器”也会生成一个IP地址,我们需要的就是后面这个IP地址,目前论坛上关于手机IP地址的帖子都是获取手机被分配的IP地址。我在解决这个问题时参考了蓝牙的配置IP地址,函数是configureBtIface(),在/frameworks/base/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java里。可以看到它也是先获取然后配置,参考这个,我写了获取热点IP地址的函数。
代码链接

private String configureBtIface(boolean enable, String iface) {
        Log.i(TAG, "configureBtIface: " + iface + " enable: " + enable);

        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
        ConnectivityManager cm =
                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();

        InterfaceConfiguration ifcg = null;
        String address = null;
        try {
            ifcg = service.getInterfaceConfig(iface);
            if (ifcg != null) {
                InetAddress addr = null;
                LinkAddress linkAddr = ifcg.getLinkAddress();
                if (linkAddr == null || (addr = linkAddr.getAddress()) == null || addr.equals(
                        NetworkUtils.numericToInetAddress("0.0.0.0")) || addr.equals(
                        NetworkUtils.numericToInetAddress("::0"))) {
                    address = BLUETOOTH_IFACE_ADDR_START;
                    addr = NetworkUtils.numericToInetAddress(address);
                }

                ifcg.setLinkAddress(new LinkAddress(addr, BLUETOOTH_PREFIX_LENGTH));
                if (enable) {
                    ifcg.setInterfaceUp();
                } else {
                    ifcg.setInterfaceDown();
                }

                ifcg.clearFlag("running");
                service.setInterfaceConfig(iface, ifcg);

                if (enable) {
                    int tetherStatus = cm.tether(iface);
                    if (tetherStatus != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                        Log.e(TAG, "Error tethering " + iface + " tetherStatus: " + tetherStatus);
                        return null;
                    }
                } else {
                    int untetherStatus = cm.untether(iface);
                    Log.i(TAG, "Untethered: " + iface + " untetherStatus: " + untetherStatus);
                }
            }
        }
        return address;
    }

下面getIpAddress()就是我写的开启热点以后获取AP端IP地址的函数,主要就是把蓝牙那边的参数改成了wlan0,就ok了。经过测试,log打出来的IP地址和手机执行ifconfig里wlan0里面的IP地址一模一样。当然,这个IP地址每次打开热点都是不一样的。在Android8.0以及之前这个IP地址是固定的,好像是"192.168.43.1"。9.0以后随机分配,可能是为了安全吧。

private String getIpAddress() {
        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
   
        InterfaceConfiguration ifcg = null;
        String address = null;
        try {
          ifcg = service.getInterfaceConfig("wlan0");
          if (ifcg != null) {
               LinkAddress linkAddr = ifcg.getLinkAddress();
               Log.d("test" , "linkAddr" + linkAddr.toString());
               if (linkAddr != null) {
                    InetAddress Inetaddr = linkAddr.getAddress();
                    Log.d("test" , "Inetaddr" + Inetaddr.toString());
                    if (Inetaddr != null) {
                         address = Inetaddr.getHostAddress();
                         if (address != null) {
                              Log.d("test" , "address " + address.toString());
                         }
                    }
               }
          }
        } catch (Exception e) {
            Log.e("test", "Error configuring interface :" + e);
            return null;
        }
        return address;
    }

这里贴上Android9.0上开启热点时分配IP地址(ipv4)的代码:/frameworks/base/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java里的configureIPv4()函数。
代码链接

private boolean configureIPv4(boolean enabled) {
        if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");

        // TODO: Replace this hard-coded information with dynamically selected
        // config passed down to us by a higher layer IP-coordinating element.
        String ipAsString = null;
        int prefixLen = 0;
        if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
            ipAsString = USB_NEAR_IFACE_ADDR;
            prefixLen = USB_PREFIX_LENGTH;
        } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
            ipAsString = getRandomWifiIPv4Address();
            prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
        } else {
            // Nothing to do, BT does this elsewhere.
            return true;
        }

        final LinkAddress linkAddr;
        try {
            final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName);
            if (ifcg == null) {
                mLog.e("Received null interface config");
                return false;
            }

            InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString);
            linkAddr = new LinkAddress(addr, prefixLen);
            ifcg.setLinkAddress(linkAddr);
            if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
                // The WiFi stack has ownership of the interface up/down state.
                // It is unclear whether the Bluetooth or USB stacks will manage their own
                // state.
                ifcg.ignoreInterfaceUpDownStatus();
            } else {
                if (enabled) {
                    ifcg.setInterfaceUp();
                } else {
                    ifcg.setInterfaceDown();
                }
            }
            ifcg.clearFlag("running");
            mNMService.setInterfaceConfig(mIfaceName, ifcg);
        } catch (Exception e) {
            mLog.e("Error configuring interface " + e);
            return false;
        }

        // Directly-connected route.
        final RouteInfo route = new RouteInfo(linkAddr);
        if (enabled) {
            mLinkProperties.addLinkAddress(linkAddr);
            mLinkProperties.addRoute(route);
        } else {
            mLinkProperties.removeLinkAddress(linkAddr);
            mLinkProperties.removeRoute(route);
        }
        return true;
    }

关注公众号,获取更多开发必备知识
在这里插入图片描述

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值