前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开启热点后作为路由器,获取AP端IP地址

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

作者头像
用户7557625
发布2020-07-15 10:37:49
2.8K0
发布2020-07-15 10:37:49
举报

最近在做类似面对面通信,需要一台手机作为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地址的函数。

代码语言:javascript
复制
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以后随机分配,可能是为了安全吧。

代码语言:javascript
复制
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()函数。

代码语言:javascript
复制
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;
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-10-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档