我想从
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
。
谢谢!
看起来这种行为是可以预见的。
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)
/**
* 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;
因此,在我的情况下,似乎未提供信号强度。
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;
}
/**
* 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); <---
...
}
/**
* 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);
}
}
/**
* 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(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
传输类型提供正确的值。