安卓显示WiFi信号强度流程

1 概要

本文主要讲述了安卓导航栏里WiFi信号的获取流程

安卓版本:各版本通用

2 整体架构流程

2.1 安卓10及其以下

a)跟WiFi UI强相关的内容,一般可以到如下目录中去寻找:packages/apps/Settings/src/com/android/settings/wifi/

b)在packages/apps/Settings/src/com/android/settings/wifi/details/下有一个WifiDetailPreferenceController.java 类,该类中会对WiFi的信息进行配置。

c)在WifiDetailPreferenceController中,首先可以看到其注册了一个BroadcastReceiver,主要接收的广播有:CONFIGURED_NETWORKS_CHANGED_ACTION、

NETWORK_STATE_CHANGED_ACTION、RSSI_CHANGED_ACTION,这里我们只关心RSSI_CHANGED_ACTION这个广播,在接受广播之后是调用了refreshPage()方法。

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
                    if (!intent.getBooleanExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED,
                            false /* defaultValue */)) {
                        // only one network changed
                        WifiConfiguration wifiConfiguration = intent
                                .getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION);
                        if (mAccessPoint.matches(wifiConfiguration)) {
                            mWifiConfig = wifiConfiguration;
                        }
                    }
                    // fall through
                case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                case WifiManager.RSSI_CHANGED_ACTION:
                    refreshPage();
                    break;
            }
        }
    };

d)在refreshPage()方法中,首先会通过updateAccessPoint()来判断AP的信息是否有更新,有更新的话其次则会refresh各类信息,这里我们只关心refreshRssiViews()。

    private void refreshPage() {
        if(!updateAccessPoint()) {
            return;
        }

        Log.d(TAG, "Update UI!");

        // refresh header
        refreshEntityHeader();

        // refresh Buttons
        refreshButtons();

        // Update Connection Header icon and Signal Strength Preference
        refreshRssiViews();
        // Frequency Pref
        refreshFrequency();
        // Transmit Link Speed Pref
        refreshTxSpeed();
        // Receive Link Speed Pref
        refreshRxSpeed();
        // IP related information
        refreshIpLayerInfo();
        // SSID Pref
        refreshSsid();
        // MAC Address Pref
        refreshMacAddress();
    }

e)在refreshRssiViews()方法中,首先就会调用mAccessPoint.getLevel()来获取当前信号强度信息;其次则会判断RSSI是否在指定范围,如果不在指定范围则将其控件不显示,并且将信号强度设置为-1;最后则是通过mIconInjector.getIcon(mRssiSignalLevel)和mSignalStrengthPref.setIcon(wifiIconDark)来设置界面的WiFi信号强度。

    private void refreshRssiViews() {
        int signalLevel = mAccessPoint.getLevel();

        // Disappears signal view if not in range. e.g. for saved networks.
        if (mIsOutOfRange) {
            mSignalStrengthPref.setVisible(false);
            mRssiSignalLevel = -1;
            return;
        }

        if (mRssiSignalLevel == signalLevel) {
            return;
        }
        mRssiSignalLevel = signalLevel;
        Drawable wifiIcon = mIconInjector.getIcon(mRssiSignalLevel);

        if (mEntityHeaderController != null) {
            mEntityHeaderController
                    .setIcon(redrawIconForHeader(wifiIcon)).done(mFragment.getActivity(),
                            true /* rebind */);
        }

        Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
        wifiIconDark.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
        mSignalStrengthPref.setIcon(wifiIconDark);

        mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
        mSignalStrengthPref.setVisible(true);
    }

f)在AccessPoint.getLevel()方法中,会调用WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS)来获取到RSSI以及信号强度。

PS:AccessPoint类中都是一些WiFi的信息,例如BSSID、SSID、安全类型、RSSI等。

    /**
     * Returns the number of levels to show for a Wifi icon, from 0 to {@link #SIGNAL_LEVELS}-1.
     *
     * <p>Use {@#isReachable()} to determine if an AccessPoint is in range, as this method will
     * always return at least 0.
     */
    public int getLevel() {
        return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
    }

g)在WifiManager.calculateSignalLevel()方法中,会通过传进来的RSSI进行信号强度的计算。首先会判断当前的Rssi是否小于最小的Rssi,并且大于最大的Rssi(MIN_RSSI=-100、MAX_RSSI=-55);其次如果当前Rssi符合要求的话,则会对WiFi信号强度进行计算,最后会对计算出的结果进行取整,并返回到UI界面中。

例:如果当前的Rssi为-60,则计算来的WiFi信号强度为:(-60+100)* 4 / (-55+100)= 3.55555556 ,最后对结果进行向下取整,最后输出的WiFi信号强度等级为3。

    /**
     * Calculates the level of the signal. This should be used any time a signal
     * is being shown.
     *
     * @param rssi The power of the signal measured in RSSI.
     * @param numLevels The number of levels to consider in the calculated
     *            level.
     * @return A level of the signal, given in the range of 0 to numLevels-1
     *         (both inclusive).
     */
    public static int calculateSignalLevel(int rssi, int numLevels) {
        if (rssi <= MIN_RSSI) {
            return 0;
        } else if (rssi >= MAX_RSSI) {
            return numLevels - 1;
        } else {
            float inputRange = (MAX_RSSI - MIN_RSSI);
            float outputRange = (numLevels - 1);
            return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
        }
    }

如上就是大致的获取WiFi信号强度的流程 ,但是这只适用于安卓10以及安卓10以下的版本,安卓11及其以上,在WifiManager.calculateSignalLevel()的使用上会有些许差别。

2.2 安卓11及其以上

a)安卓10和安卓11的差别在于AccessPoint.getLevel()方法,可以看到安卓10传进了两个参数,而安卓11只传进了一个参数。

安卓10:WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS)

安卓11:getWifiManager().calculateSignalLevel(mRssi)

b)其次在WifiManager中可以看到,  calculateSignalLevel(int rssi, int numLevels)是被废弃的接口,而真正被使用的是calculateSignalLevel(int rssi)这个接口。在calculateSignalLevel()方法中则会调用WifiServiceImpl的calculateSignalLevel()方法。

c)在WifiServiceImpl.calculateSignalLevel()方法中,会调用RssiUtil.calculateSignalLevel()。

    @Override
    public int calculateSignalLevel(int rssi) {
        return RssiUtil.calculateSignalLevel(mContext, rssi);
    }

d)在RssiUtil.calculateSignalLevel()方法中首先会通过getRssiLevelThresholds()来获取到rssi对应的信号强度;其次通过循环计算出当前的信号强度为多少。

数组thresholds的具体数值如下:

    <integer-array translatable="false" name="config_wifiRssiLevelThresholds">
                         <!-- RSSI                RSSI Level -->
        <item>-88</item> <!-- (-infinity, -88)             0 -->
        <item>-77</item> <!-- [-88, -77)                   1 -->
        <item>-66</item> <!-- [-77, -66)                   2 -->
        <item>-55</item> <!-- [-66, -55)                   3 -->
                         <!-- [-55, +infinity)             4 -->
    </integer-array>

例:如果当前的Rssi为-60,首先会对比thresholds[0],-60>-88;继续进行对比thresholds[1],-60>-77;继续进行对比thresholds[2],-60>-66;继续进行对比thresholds[3]。-60<-55,所以当前RSSI对应的信号强度为:3。

    /** Calculate RSSI level from RSSI using overlaid RSSI level thresholds. */
    public static int calculateSignalLevel(Context context, int rssi) {
        int[] thresholds = getRssiLevelThresholds(context);

        for (int level = 0; level < thresholds.length; level++) {
            if (rssi < thresholds[level]) {
                return level;
            }
        }
        return thresholds.length;
    }

    @NonNull
    private static int[] getRssiLevelThresholds(Context context) {
        // getIntArray() will never return null, it will throw instead
        return context.getResources().getIntArray(R.array.config_wifiRssiLevelThresholds);
    }

3 小结

 RSSI对应的信号强度差不多就是通过如上流程来获取的,如果要是客户有一些定制化的需求,例如要修改RSSI的阈值:

a)安卓10及其以下则可以通过修改WifiManager.calculateSignalLevel()中计算RSSI对应信号强度的逻辑来达到目的。(rssi在某个范围内就返回多少的信号强度)

b)在安卓11及其以上则可以通过修改packages/modules/Wifi/service/ServiceWifiResources/res/values/config.xml中config_wifiRssiLevelThresholds的<item>值来达到目的。

  • 55
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值