#android #hotspot #android-connectivitymanager
Вопрос:
Я зарегистрировал ConnectivityManager сетевой обратный вызов следующим образом:
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val builder = NetworkRequest.Builder()
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
cm.registerNetworkCallback(
builder.build(),
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
Log.i(TAG, "Network $network is available")
}
override fun onLosing(network: Network, maxMsToLive: Int) {
super.onLosing(network, maxMsToLive)
Log.i(TAG, "Network $network is losing after $maxMsToLive ms")
}
override fun onLost(network: Network) {
super.onLost(network)
Log.i(TAG, "Network $network is lost")
}
override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
super.onCapabilitiesChanged(network, caps)
Log.i(TAG, "Network $network capabilities changed: $caps")
}
override fun onLinkPropertiesChanged(network: Network, props: LinkProperties) {
super.onLinkPropertiesChanged(network, props)
Log.i(TAG, "Network $network link properties changed: $props")
}
}
}
Когда я включаю/выключаю точку доступа на своем устройстве Android 11, ни одна из функций обратного вызова не вызывается, т. Е. Я не получаю никаких сообщений в logcat, когда я включаю/выключаю точку доступа Wi-Fi.
Когда точка доступа отключена, у устройства есть эти адреса:
PAN_sprout:/ $ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 46:85:2d:8f:9a:8e brd ff:ff:ff:ff:ff:ff
inet6 fe80::4485:2dff:fe8f:9a8e/64 scope link
valid_lft forever preferred_lft forever
3: ip_vti0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/ipip 0.0.0.0 brd 0.0.0.0
4: ip6_vti0@NONE: <NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1
link/tunnel6 :: brd ::
5: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
6: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1
link/tunnel6 :: brd ::
8: rmnet0: <UP,LOWER_UP> mtu 2000 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/[530]
9: rmnet_data0: <UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/[530]
inet6 fe80::9e2:b3d5:84e6:14c/64 scope link
valid_lft forever preferred_lft forever
10: rmnet_data1: <UP,LOWER_UP> mtu 1464 qdisc htb state UNKNOWN group default qlen 1000
link/[530]
inet 10.140.85.190/30 scope global rmnet_data1
valid_lft forever preferred_lft forever
inet6 2001:14bb:a0:5545:818d:5109:4166:b991/64 scope global dynamic mngtmpaddr
valid_lft forever preferred_lft forever
inet6 fe80::818d:5109:4166:b991/64 scope link
valid_lft forever preferred_lft forever
...
25: r_rmnet_data8: <> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/[530]
and when I turn it on, device has these addresses:
PAN_sprout:/ $ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 46:85:2d:8f:9a:8e brd ff:ff:ff:ff:ff:ff
inet6 fe80::4485:2dff:fe8f:9a8e/64 scope link
valid_lft forever preferred_lft forever
3: ip_vti0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/ipip 0.0.0.0 brd 0.0.0.0
4: ip6_vti0@NONE: <NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1
link/tunnel6 :: brd ::
5: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
6: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1
link/tunnel6 :: brd ::
8: rmnet0: <UP,LOWER_UP> mtu 2000 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/[530]
9: rmnet_data0: <UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/[530]
inet6 fe80::9e2:b3d5:84e6:14c/64 scope link
valid_lft forever preferred_lft forever
10: rmnet_data1: <UP,LOWER_UP> mtu 1464 qdisc htb state UNKNOWN group default qlen 1000
link/[530]
inet 10.140.85.190/30 scope global rmnet_data1
valid_lft forever preferred_lft forever
inet6 2001:14bb:a0:5545:818d:5109:4166:b991/64 scope global dynamic mngtmpaddr
valid_lft forever preferred_lft forever
inet6 fe80::818d:5109:4166:b991/64 scope link
valid_lft forever preferred_lft forever
...
25: r_rmnet_data8: <> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/[530]
176: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 7a:d1:a3:76:b8:8a brd ff:ff:ff:ff:ff:ff
inet 192.168.214.149/24 brd 192.168.214.255 scope global wlan0
valid_lft forever preferred_lft forever
inet6 2001:14bb:a0:5545::5a/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::78d1:a3ff:fe76:b88a/64 scope link
valid_lft forever preferred_lft forever
Как вы видите, был добавлен wlan0, но функция обратного вызова не вызывалась. Функции обратного вызова работают иначе, например, когда я включаю/выключаю сотовую сеть.
Вопрос в следующем: что мне нужно сделать, чтобы функции обратного вызова вызывались при включении/выключении точки доступа Wi-Fi.
Редактировать: Основываясь на ответе Серджио Пардо, я создал это:
val hotSpotReceiver = object : BroadcastReceiver() {
override fun onReceive(contxt: Context, intent: Intent) {
val action = intent.action
if ("android.net.wifi.WIFI_AP_STATE_CHANGED" == action) {
val state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0)
if (WifiManager.WIFI_STATE_ENABLED == state % 10)
Log.d(TAG, "HotSpot is enabled")
else
Log.d(TAG, "HotSpot is disabled")
}
}
}
}
this.registerReceiver(hotSpotReceiver,
IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED"))
Он может быть использован для определения того, включена или отключена точка доступа Wi-Fi, и отвечает на название вопроса. Но это не помогает в вызове обратных вызовов сети.
Обратные вызовы позволили бы мне узнать локальный IP-адрес точки доступа и имя интерфейса. Есть ли какой-то другой способ выяснить это?
Редактировать: Оказалось, что, когда указанный выше hotSpotReceiver регистрирует «Точка доступа включена», возникает задержка, прежде чем интерфейс точки доступа получит свои IP-адреса и маршруты. Отсутствующие сетевые обратные вызовы помогли бы.
Ответ №1:
Я думаю, что вы пытаетесь использовать неправильную системную службу и ее последующую реализацию. Вы должны использовать «Контекст.WIFI_SERVICE», и это даст вам менеджер Wi-Fi.
val manager = getSystemService(Context.CONNECTIVITY_SERVICE) as WifiManager
И затем вы можете использовать это значение, чтобы узнать, включена ли точка доступа:
public static boolean isHotspotOn(final WifiManager manager) {
try {
final Method method =
manager.getClass().getDeclaredMethod("isWifiApEnabled");
return (Boolean) method.invoke(manager);
} catch (final Throwable ignored) {}
return false;
}
Если вы также хотите слушать обновления точки доступа, вам следует сделать это с помощью следующего фильтра намерений
IntentFilter filter = new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED");
Комментарии:
1. Спасибо за ваш ответ. Я попробую это сделать. Согласно документации разработчика Android, ConnectivityManager «Отслеживает сетевые подключения (Wi-Fi, GPRS, UMTS и т. Д.), Отправляет намерения вещания при изменении сетевого подключения…». Наверняка, когда точка доступа Wi-Fi включена, происходит изменение сетевого подключения, и устройство, на котором расположена точка доступа, может начать через сеть Wi-Fi точки доступа общаться с другими сторонами. Если Connectivitymanager не имеет никакого отношения к изменениям подключения, связанным с точкой доступа Wi-Fi, существует большая проблема с официальной документацией ConnectivityManager.
Ответ №2:
Ответ Google на мой отчет об ошибке:
Это известное ограничение всех реализаций Android начиная с Android 12. Мы стремимся улучшить это в будущем, но на данный момент не можем поделиться сроками.
Затем они закрыли отчет об ошибке со статусом Won't Fix (Intended behavior)
. Я постараюсь усилить это, поскольку поведение, противоречащее официальной документации API и предотвращающее реакцию приложения на изменения сетевого подключения, не может быть «Предполагаемым поведением».