使用Android获取当前的互联网速度(移动网络和Wifi)。

21

我有一个应用程序,必须可以在线和离线工作。应用程序必须根据当前网络连接(Wifi或数据)的互联网速度向应用服务器发出请求。

如果已连接Wifi,则可以使用此代码获取当前连接的Wifi信号强度。

WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int level = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 5);

或者

wifiInfo.getLinkSpeed();
如果手机互联网已连接,则可以使用监听器类获得信号强度。
@Override
    public void onSignalStrengthsChanged(SignalStrength signalStrength) {
        super.onSignalStrengthsChanged(signalStrength);
        int obj  = signalStrength.getGsmSignalStrength();
        int dBm = (2 * obj) -113;
 }

以上代码获取的是信号强度,而不是速度。那么,如何获取当前连接网络的速度?

通常,在商店或网站中找到的速度测试应用程序通过发送或下载特定文件或ping远程服务器,然后使用经过的时间计算速度来检查速度。

该应用程序服务器不支持此上传/下载或ping功能,因此我无法使用它。

那么,有没有其他替代方法可以实时检查当前互联网连接的速度?

任何提示都可能有所帮助。

PS:此链接包含用于检查当前网络连接类型的代码。但是,有些情况下我拥有满格的LTE信号但没有/非常缓慢的互联网连接。因此,这也不能成为我准确的解决方案。

https://gist.github.com/emil2k/5130324


这是一个指向Stack Overflow上的答案链接,可能会对你有所帮助。 - user5722294
人们使用ping的原因是因为没有其他方法可以精确地测量。一个链接可能支持高达100Mbps,但由于拥塞你只能获得2Mbps。唯一的方法是进行计算。如果你想访问拥挤且只能支持10Mbps的bar.com,那么知道你的链接支持100Mbps到foo.com也没有什么帮助。任何其他方法都只是一个近似值。 - Gabe Sechan
发现了一篇有用的 Medium 文章。看一下:https://android.jlelse.eu/designing-android-apps-to-handle-slow-network-speed-dedc04119aac - Nabeel K
你试过这个示例吗:https://github.com/bertrandmartel/speed-test-lib - Ankit Mehta
@Ankit Mehta,没有,我还没有尝试过这个样例。在我的理解中,如果没有对任何服务器进行ping操作,就无法检查连接速度。 - user198530
2个回答

5
您无法在不对任何服务器进行ping的情况下获得下载/上传速度。由于您的服务器不支持ping,因此可以使用第三方ping站点。
使用JSpeedTest库可以轻松完成此操作。该库提供了一些所需的功能,例如:
- 速度测试下载 - 速度测试上传 - 下载/上传进度监控 - 可配置的主机名/端口/URI(FTP的用户名和密码) - 可配置的套接字超时和块大小 - 配置上传文件存储
Gradle:
compile 'fr.bmartel:jspeedtest:1.32.1'

示例代码:

SpeedTestSocket speedTestSocket = new SpeedTestSocket();

// add a listener to wait for speedtest completion and progress
speedTestSocket.addSpeedTestListener(new ISpeedTestListener() {

    @Override
    public void onCompletion(SpeedTestReport report) {
        // called when download/upload is complete
        System.out.println("[COMPLETED] rate in octet/s : " + report.getTransferRateOctet());
        System.out.println("[COMPLETED] rate in bit/s   : " + report.getTransferRateBit());
    }

    @Override
    public void onError(SpeedTestError speedTestError, String errorMessage) {
         // called when a download/upload error occur
    }

    @Override
    public void onProgress(float percent, SpeedTestReport report) {
        // called to notify download/upload progress
        System.out.println("[PROGRESS] progress : " + percent + "%");
        System.out.println("[PROGRESS] rate in octet/s : " + report.getTransferRateOctet());
        System.out.println("[PROGRESS] rate in bit/s   : " + report.getTransferRateBit());
    }
});

我想检查互联网速度并相应地设置图像或视频URL。例如,如果当前互联网速度在50kbps - 150 kbps之间,则链接到link1;如果在150kbps - 500kbps之间,则链接到link2;如果大于500kbps,则链接到link3。那么如何实现呢? - Bhavin Patel
这个库在 VPN 上无法工作,我尝试了 speedTestSocket.setProxyServer("http://216.56.48.118:9000");,但它抛出了错误 INVALID_HTTP_RESPONSE:解析 http 帧时发生错误和 INVALID_HTTP_RESPONSE:错误状态码 -1。 - Harsh Gupta

3
你可以简单地将名为TrafficUtils的类添加到你的项目中,并调用以下方法 -
TrafficUtils.getNetworkSpeed()

首先,在AndroidManifest.xml文件中添加以下两个权限 -

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"

这个类使用TrafficStats.getMobileRxBytes方法来返回通过移动网络接收的总数据量,然后等待一秒钟再次调用该方法,以找到两个数字之间的差异。这并不准确地表示用户网络的当前速度。如果用户设备当前没有进行太多的网络操作,那么这个数字会比在同一个网络中同时调用该方法时用户在后台下载某些内容时要低。 - kimchibooty

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