具有 NetworkCapability 的 NetworkCallback 仅被调用一次

问题描述 投票:0回答:1

我想从

getLinkDownstreamBandwidthKbps()
班的
getLinkUpstreamBandwidthKbps()
getSignalStrength()
NetworkCapabilities
获取信息。 为此,我在
MainActivity
中执行以下操作:

private static ConnectivityManager connectivityManager;

...

@Override
protected void onCreate(final Bundle savedInstanceState) {
    connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
}

private final NetworkRequest networkRequest = new NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .build();

private final NetworkCallback networkCallback = new NetworkCallback() {
    @Override
    public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
        int dLBandwidth = networkCapabilities.getLinkDownstreamBandwidthKbps();
        int uLBandwidth = networkCapabilities.getLinkUpstreamBandwidthKbps();
        int signalStrength = networkCapabilities.getSignalStrength();

        final String timestamp = Util.getCurrentTimestamp();
        Util.log(String.format(Locale.US, "CM::%s::dLBandwidth=%d::uLBandwidth=%d::sStrength=%d\n",
                timestamp, dLBandwidth, uLBandwidth, signalStrength));
    }
};

private View getStartButton() { // button click handler
    connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
}

private View getStopButton() { // button click handler
    connectivityManager.unregisterNetworkCallback(networkCallback);
}

由于某种原因,我在日志中只得到一项。

CM::2023-09-17 13:11:07.882::dLBandwidth=30000::uLBandwidth=15000::sStrength=-2147483648

因此,

NetworkCallback
只被调用一次,尽管我带着电话在家里移动,信号强度发生了变化。 有人可以建议这种行为的原因是什么吗?我做错了什么?

就我而言

minSdkVersion 29
compileSdk 33

谢谢!

android android-connectivitymanager
1个回答
0
投票

看起来这种行为是可以预见的。

  1. SignalStrength
    ==
    -2147483648
    ==
    Integer.MIN_VALUE
    == 信号强度未指定

根据文档,其含义如下:

Magic value that indicates no signal strength provided. A request specifying this value is always satisfied.

Constant Value: -2147483648 (0x80000000)

网络功能.java:1758

/**
 * Magic value that indicates no signal strength provided. A request specifying this value is
 * always satisfied.
 */
public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE;

因此,在我的情况下,似乎未提供信号强度。

  1. LinkDownstreamBandwidth
    ==
    30000
    LinkUpstreamBandwidth
    ==
    15000

就我而言,我得到了这些magic数字,但它们从未更新。如果我们跟踪这些值的 setter 调用序列,我们会得到以下序列:

setLinkDownstreamBandwidthKbps:3013

/**
 * Sets the downstream bandwidth for this network in Kbps. This always only refers to
 * the estimated first hop transport bandwidth.
 * <p>
 * Note that when used to request a network, this specifies the minimum acceptable.
 * When received as the state of an existing network this specifies the typical
 * first hop bandwidth expected. This is never measured, but rather is inferred
 * from technology type and other link parameters. It could be used to differentiate
 * between very slow 1xRTT cellular links and other faster networks or even between
 * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between
 * fast backhauls and slow backhauls.
 *
 * @param downKbps the estimated first hop downstream (network to device) bandwidth.
 * @return this builder
 */
@NonNull
public Builder setLinkDownstreamBandwidthKbps(final int downKbps) {
    mCaps.setLinkDownstreamBandwidthKbps(downKbps);
    return this;
}

更新网络能力:2080

/**
 * Update the network capabilities.
 */
private void updateNetworkCapabilities() {
    final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
    boolean roaming = mPhone.getServiceState().getDataRoaming();
    ...
    // Set the bandwidth information.
    builder.setLinkDownstreamBandwidthKbps(mNetworkBandwidth.downlinkBandwidthKbps);    <---
    builder.setLinkUpstreamBandwidthKbps(mNetworkBandwidth.uplinkBandwidthKbps);        <---
    ...
}

网络带宽:715

/**
 * The network bandwidth.
 */
public static class NetworkBandwidth {
    /** The downlink bandwidth in Kbps. */
    public final int downlinkBandwidthKbps;

    /** The uplink Bandwidth in Kbps. */
    public final int uplinkBandwidthKbps;

    /**
     * Constructor.
     *
     * @param downlinkBandwidthKbps The downlink bandwidth in Kbps.
     * @param uplinkBandwidthKbps The uplink Bandwidth in Kbps.
     */
    public NetworkBandwidth(int downlinkBandwidthKbps, int uplinkBandwidthKbps) {    <---
        this.downlinkBandwidthKbps = downlinkBandwidthKbps;
        this.uplinkBandwidthKbps = uplinkBandwidthKbps;
    }

    @Override
    public String toString() {
        return String.format("NetworkBandwidth=[downlink=%d, uplink=%d]",
                downlinkBandwidthKbps, uplinkBandwidthKbps);
    }
}

更新带宽:801

/**
 * Update the downlink and uplink bandwidth values from the carrier config.
 */
private void updateBandwidths() {
    synchronized (this) {
        mBandwidthMap.clear();
        String[] bandwidths = mCarrierConfig.getStringArray(
                CarrierConfigManager.KEY_BANDWIDTH_STRING_ARRAY);           <---
        boolean useLte = mCarrierConfig.getBoolean(CarrierConfigManager
                .KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPLINK_BOOL);
        if (bandwidths != null) {
            for (String bandwidth : bandwidths) {
                // split1[0] = network type as string
                // split1[1] = downlink,uplink
                String[] split1 = bandwidth.split(":");
                if (split1.length != 2) {
                    loge("Invalid bandwidth: " + bandwidth);
                    continue;
                }
                // split2[0] = downlink bandwidth in kbps
                // split2[1] = uplink bandwidth in kbps
                String[] split2 = split1[1].split(",");
                if (split2.length != 2) {
                    loge("Invalid bandwidth values: " + Arrays.toString(split2));
                    continue;
                }
                int downlink, uplink;
                try {
                    downlink = Integer.parseInt(split2[0]);
                    uplink = Integer.parseInt(split2[1]);
                } catch (NumberFormatException e) {
                    loge("Exception parsing bandwidth values for network type " + split1[0]
                            + ": " + e);
                    continue;
                }
                if (useLte && split1[0].startsWith("NR")) {
                    // We can get it directly from mBandwidthMap because LTE is defined before
                    // the NR values in CarrierConfigManager#KEY_BANDWIDTH_STRING_ARRAY.
                    uplink = mBandwidthMap.get(DATA_CONFIG_NETWORK_TYPE_LTE)
                            .uplinkBandwidthKbps;
                }
                mBandwidthMap.put(split1[0],
                        new DataNetwork.NetworkBandwidth(downlink, uplink));
            }
        }
    }
}

KEY_BANDWIDTH_STRING_ARRAY:2996

/**
 * String array of default bandwidth values per network type.
 * The entries should be of form: "network_name:downlink,uplink", with values in Kbps.
 * For NR (5G), the following network names should be used:
 * - NR_NSA: NR NSA, sub-6 frequencies
 * - NR_NSA_MMWAVE: NR NSA, mmwave frequencies
 * - NR_SA: NR SA, sub-6 frequencies
 * - NR_SA_MMWAVE: NR SA, mmwave frequencies
 * @hide
 */
public static final String KEY_BANDWIDTH_STRING_ARRAY = "bandwidth_string_array";

sDefaults.putStringArray:9168

sDefaults.putStringArray(KEY_BANDWIDTH_STRING_ARRAY, new String[]{
            "GPRS:24,24", "EDGE:70,18", "UMTS:115,115", "CDMA:14,14",
            "1xRTT:30,30", "EvDo_0:750,48", "EvDo_A:950,550", "HSDPA:4300,620",
            "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo_B:1500,550", "eHRPD:750,48",
            "iDEN:14,14", "LTE:30000,15000", "HSPA+:13000,3400", "GSM:24,24",
            "TD_SCDMA:115,115", "LTE_CA:30000,15000", "NR_NSA:47000,18000",
            "NR_NSA_MMWAVE:145000,60000", "NR_SA:145000,60000", "NR_SA_MMWAVE:145000,60000"});

因此,我可以假设对于用于测试的设备,我只能获得

CELLULAR
传输类型的默认值。也许调制解调器固件/驱动程序不会公开此类数据。 同时,此 API 为
WIFI
传输类型提供正确的值。

© www.soinside.com 2019 - 2023. All rights reserved.