如何在Android上检测网络是否配置为移动热点?

7

从Android 4.1开始,您的设备可以检测是否连接到移动热点(假设移动热点也在运行Android 4.1或更高版本)。此外,您可以将网络标记为移动热点(Settings/Data Usage/Overflow menu/Mobile Hotspots)。

但是,作为开发者的我该如何检测它呢?因为它并没有存储在WifiConfiguration中,那么它在哪里呢?

一些背景信息:我想构建一个简单的Android工具,用于检查您是否连接到已被您或Android标记为移动热点的网络。如果是这样,它将检查是否有其他(非热点)网络可用。如果是这样,应该连接到这些其他网络,因为那些网络应该速度更快且没有数据限制。为什么?因为我的手机和平板经常连接到(移动)热点,即使有更好的网络可用。

下面是我正在寻找的伪代码:

// Check if android has detected mobile hotspot
WifiManager wifiMgr = getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiMgr .getConnectionInfo();
boolean isMobileHotspot = wifiInfo.isMobileHotspot;

2014年7月3日更新

好的,Matiash的答案是不错的,但是ConnectivityManager.isActiveNetworkMetered()只会返回当前网络的值。我确实需要这个值,所以它帮助了我,但是它让我来到了我工具/应用程序的下一部分:

如果设备连接到移动热点(或Android所称的“计量网络”),我想检查是否有任何附近的接入点是更好的选择。因此,在连接到它之前,我需要知道是否已将任何已知AP(WifiManager.getConfiguredNetworks())标记为此类...

我有一个List<ScanResult>和一个List<WifiConfiguration>,看起来两者都没有这些信息。

这使我回到了最初的问题:是否有办法从数据使用情况下检索移动热点(由Android和/或用户配置)?这一次,我指的是所有移动热点。

2014年7月7日更新

我在AOSP问题跟踪器中发布了一个特性请求,以访问(只读)NetworkPolicyManager。请在此处对其进行投票:https://code.google.com/p/android/issues/detail?id=73206&thanks=73206&ts=1404719243


最好为“它将我带到工具/应用程序的下一部分”提出单独的问题。我可能会缓存最近连接过的已知网络,并在缓存中维护一个“isMetered”标志。 - Jeroen Wiert Pluimers
1
是的,这就是我现在正在做的。我会发布更新和/或开一个新问题。谢谢 :) - REJH
有任何更新吗?你找到解决方法了吗? - Shreyans
不行。我监控网络并自己跟踪计量网络,安卓系统不允许检测到这一点。 - REJH
3个回答

6
您可以通过调用ConnectivityManager.isActiveNetworkMetered()来访问此信息。

这将返回激活连接是否为热点(如数据使用情况 -> 移动热点中定义)。

关于第二部分,很抱歉,我不认为这是可能的。该标志不是公共的,即使您通过反射获取可用于检索它的对象(android.net.NetworkPolicyManager):

Object npm = Class.forName("android.net.NetworkPolicyManager").getDeclaredMethod("from", Context.class).invoke(null, this);
Object policies = npm.getClass().getDeclaredMethod("getNetworkPolicies").invoke(npm);

调用getNetworkPolicies()需要MANAGE_NETWORK_POLICY权限,该权限的保护级别为“签名”,因此非系统应用程序无法获取该权限。希望我的理解是错误的 :) 也许查看管理此信息的Android活动的源代码(https://github.com/android/platform_packages_apps_settings/blob/master/src/com/android/settings/net/DataUsageMeteredSettings.java),特别是buildWifiPref()方法,可以提供一些线索。

啊。但现在的问题是:在连接到已知网络(从WifiManager.getConfiguredNetworks()获取的列表)之前,有没有办法找出它是否是“计量网络”? - REJH
编辑了原帖并移除了“已回答”标记,因为这不是我正在寻找的完整答案。请参见原帖获取详细信息。 - REJH
1
@REJH 编辑了答案。希望你能找到解决方案,但恐怕这是不可能的。抱歉。 - matiash
谢谢。嗯,你的回答确实帮助我至少检测出当前网络是否计量。我一直在研究AOSP设置应用程序,看看它们是如何做到的,看起来它们使用android.net.NetworkTemplate和.NetworkTemplateEditor。不幸的是,“import android.NetworkTemplate”无法工作。我想尝试Java反射(或者叫什么名字)。无论如何,如果我找到有用的东西,我会更新这篇文章。 编辑:哈哈,刚看到你指引我朝那个方向。再次感谢。 - REJH

0
    //Check if hotspot tethering is enabled
    try {
        ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        boolean isMobileData = connectivityManager.isActiveNetworkMetered();

        if(isMobileData) {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface networkInterface : interfaces) {
                if (networkInterface.getName().equals("ap0")) {
                    //Tethering is enabled
                    SendHotspotEnabledHandler sendHotspotEnabledHandler = new SendHotspotEnabledHandler(new WeakReference<Context>(SendInstalledAppsService.this));
                    sendHotspotEnabledHandler.execute();
                    break;
                }
            }
        }

    } catch (SocketException e) {
    }

0

我不确定您想要的是否可能,但您可以通过检查IP地址来检查设备是否连接到网络。

您可以使用下面的工具查看您是否拥有IP地址,并了解是否连接到网络。

public static Boolean check_connection(final Context _context)
  {
      boolean connected;

      ConnectivityManager conectivtyManager = (ConnectivityManager) _context
              .getSystemService(Context.CONNECTIVITY_SERVICE);

      if (conectivtyManager.getActiveNetworkInfo() != null
              && conectivtyManager.getActiveNetworkInfo().isAvailable()
              && conectivtyManager.getActiveNetworkInfo().isConnected())
      {
          connected = true;

      } else
      {
          connected = false;
      }
      return connected;
  }

谢谢但这不是我要找的。mataish找到了我想要的东西。无论如何还是谢谢:D - REJH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接