Android 9 — время ожидания подключения к сокету при включении мобильных данных

У меня есть развернутое приложение, которое не работает на Android 9. Частью его функции является настройка модуля в сети точки доступа, чтобы этот модуль мог подключаться к домашней сети пользователей.

У меня есть код, который обнаруживает и подключается к правильной сети WIFI, но когда я пытаюсь открыть сокет для устройства, он терпит неудачу - только на Android 9 и только если включены мобильные данные. Если я вручную отключу мобильные данные на устройстве, все будет работать нормально.

Socket open() {
    Socket sock = new Socket(Proxy.NO_PROXY);
    try {
        sock.bind(new InetSocketAddress(localIpAddress(), 50000));
    } catch (IOException e) {
        activity.logContent("Warning: Failed to bind socket : " + e.toString());
    }
    try {
        sock.connect(new InetSocketAddress("192.168.17.1", 5555), (int)5000);
    } catch (IOException e) {
        // This catch fires when Mobile Data is on.
        activity.logContent("Connected to " + activity.mWifiManager.getConnectionInfo().getSSID());
        activity.logContent("Couldn't open socket : " + e.toString());
    }
    return sock;
}

Я пробовал это с вызовом Proxy.NO_PROXY и без него, а также с вызовом bind() и без него. Если вызов привязки отсутствует, ошибка означает, что сокет пытается подключиться через сотовую сеть. (Примечание: activity.logContent() — это экранный журнал, поэтому проще увидеть, что происходит, когда не подключен к отладчику).

Любые идеи, что происходит не так?


person Stephen Orr    schedule 09.05.2019    source источник
comment
перейдите по этой ссылке stackoverflow.com/questions/35152417/ у меня такая же проблема   -  person Utsav Thakkar    schedule 07.06.2019


Ответы (3)


Я считаю, что после нескольких дней проклятий я пришел к определению проблемы и, следовательно, к решению:

Проблема возникает из-за некоторых изменений в версии андроида (предполагаю, что это 9.0, даже если другие изменения произошли в API 21), в частности, при создании сокета, если система обнаруживает, что есть «лучшая» сеть. (доступ к Интернету, высокий уровень сигнала и т. д. и т. д.) создание сокета относится к этой сети, а не к сети Wi-Fi, которую вы хотели бы.

Я искал способы принудительно создать сокет в сети Wi-Fi (это сеть, которую я хочу), и единственный способ, который я нашел, это:

Проще говоря вместо:

Носок сокета = новый сокет ();

Do:

ConnectivityManager connectivity = (ConnectivityManager) MyApp.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
                if (connectivity != null)
                {
                    for (Network network : connectivity.getAllNetworks())
                    {
                        NetworkInfo networkInfo = connectivity.getNetworkInfo(network);

                        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI)
                        {
                            if (networkInfo.isConnected())
                            {
                                Socket sock =  network.getSocketFactory().createSocket();
                            }
                        }
                    }
            }

Практически просмотрите сети, присутствующие в устройстве, и когда вы найдете активный Wi-Fi, вы ничего не сделаете, кроме как воспользоваться этой функцией, чтобы наверняка получить правильный разъем:

getSocketFactory().createSocket()

Теперь у вас есть рабочая розетка!

В моем случае теперь работает отлично, если кто-то найдет лучшие решения, то это только приветствуется, но пока это единственный способ, который я нашел, чтобы все работало как в предыдущей версии андроида.

person Bronz    schedule 19.08.2019
comment
Мой клиент подтвердил, что это решило их проблемы. Спасибо. - person Stephen Orr; 28.08.2019

В Android 9 есть конфигурация безопасности для сети: Конфигурация безопасности Android

Добавление вашего домена в network_security_config может решить вашу проблему. У меня было это в моем network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">119.xxx.xxx.xxx</domain>
    </domain-config>
</network-security-config>
person StoneLam    schedule 10.05.2019
comment
Спасибо за это предложение, на самом деле у меня уже есть этот файл, но проект построен для 19, поэтому я не уверен, что файл разрешений используется. Также я (верю?) В этом случае вы получаете другую ошибку (не тайм-аут, а ошибку безопасности), и это не объясняет, почему код работает, когда мобильные данные отключены (таким образом заставляя сокет подключаться через Wi-Fi ?) - person Stephen Orr; 10.05.2019

Я не уверен в точной причине, почему это происходит. Однако, когда вы включаете свои мобильные данные и подключаетесь к Интернету только с использованием своих мобильных данных (учитывая, что ваш Wi-Fi отключен), он получает IP-адрес из сотовой сети, которая больше не подключена к вашей домашней сети. Следовательно, ожидать таких сценариев тайм-аута тривиально, потому что он не может получить доступ к частным IP-адресам вашей домашней сети, начинающимся с 192.168.....

Теперь меня смущает то, что даже если мобильные данные включены, и Wi-Fi, и мобильные данные включены одновременно, устройство должно подключаться к Wi-Fi по умолчанию.

Поэтому я хотел бы предложить вам проверить следующее.

  • В Android 9 (Pie) представлены специальные Настройки Wi-Fi, которые предотвращают автоматическое подключение к общедоступным сетям. Вы можете рассмотреть возможность проверки настроек.
  • Пожалуйста, проверьте IP-адрес вашего устройства и убедитесь, что его IP-адрес начинается с 192.168..... Если нет, то определенно вы получаете свой IP-адрес из своей сотовой сети и, следовательно, он не может достичь ваших частных IP-адресов домашней сети.
person Reaz Murshed    schedule 10.05.2019
comment
Спасибо за указание предпочтения WiFi. Устройство, которое у нас есть, также включает возможность устанавливать для нас определенные приложения или не использовать мобильные данные. Изменение этих настроек не имеет никакого значения. Вызов localIpAddress() на устройстве разрешается в 192.168.17.2, который является IP-адресом точки доступа устройства. - person Stephen Orr; 10.05.2019