Wysyłanie danych przez wifi (bez internetu), gdy dane mobilne są włączone

Rozwijam aplikację, która łączy się z urządzeniem sprzętowym przez wifi (generowane przez urządzenie) i wysyła do niego dane poprzez połączenie z gniazdem. Problem polega na tym, że gdy dane mobilne (3G/4G) jest aktywowany android próbuje wysłać dane przez niego zamiast wysyłać je przez Wi-Fi generowane przez urządzenie, ponieważ Wi-Fi nie ma połączenia z Internetem. Myślałem o użyciu Connectitymanager # setNetworkPreference () ale zostało to przestarzałe w api 21.

Jak ustawić wysyłanie danych za pomocą wifi generowanego przez urządzenie zamiast mobilnego interfejsu danych?

Author: hygorxaraujo, 2016-02-02

2 answers

Po wielu badaniach i czasie próbującym to wszystko zrozumieć, dowiedziałem się, że nie jest to możliwe w wersjach wcześniejszych niż Android 5.0 (Lollipop), system operacyjny utrzymuje tylko jeden interfejs sieciowy na raz i aplikacje nie mają nad tym kontroli.

Więc aby to zrobić na wersjach większych lub równych Lizakowi zrobiłem:

  1. przed wykonaniem połączenia z gniazdem sprawdź, czy android jest większy lub równy Lizakowi, na wypadek, gdybyś nie zrobił tego, co musisz zrobić normalnie;
  2. W przypadku, gdy wersja jest równa lub większa od Lollipop musisz zrobić coś takiego:

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        final ConnectivityManager manager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkRequest.Builder builder;
        builder = new NetworkRequest.Builder();
        //set the transport type do WIFI
        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    manager.bindProcessToNetwork(network);
                } else {
                    //This method was deprecated in API level 23
                    ConnectivityManager.setProcessDefaultNetwork(network);
                }
                try {
                    //do a callback or something else to alert your code that it's ok to send the message through socket now
                } catch (Exception e) {
                    e.printStackTrace();
                }
                manager.unregisterNetworkCallback(this);
            }
        });
    }
    
  3. Po zakończeniu powinieneś przestać wiązać proces z tym:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        ConnectivityManager manager = (ConnectivityManager) InovePlugApplication.getContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        manager.bindProcessToNetwork(null);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        ConnectivityManager.setProcessDefaultNetwork(null);
    }
    

Ta odpowiedź pomogła mi zrozumieć, jak to zrobić https://stackoverflow.com/a/29837637/2550932 .

 12
Author: hygorxaraujo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:34

Sieć przełączy się z powrotem na telefon komórkowy po setProcessDefaultNetwork na wifi, nie można wysyłać dużych danych w ten sposób, ponieważ wszystkie gniazda utworzone w ten sposób przestaną działać. Nie znajduję teraz idealnego sposobu, tutaj jest tylko w celach informacyjnych.

1.Jeśli możesz uzyskać dostęp do roota, zrób to przed połączeniem z Wi-Fi:

Process process = runtime.exec("su");
DataOutputStream dataOutputStream = new DataOutputStream(process.getOutputStream());
dataOutputStream.writeBytes("settings put global captive_portal_server 127.0.0.1\n");
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
int status = process.waitFor();

I usuń go po wysłaniu danych:

dataOutputStream.writeBytes("settings delete global captive_portal_server\n");

2.Jeśli możesz uzyskać uprawnienia WRITE_SECURE_SETTINGS:

Settings.Global.putString(getContentResolver(),"captive_portal_server","127.0.0.1");

Lub:

Settings.Global.putInt(getContentResolver(),"captive_portal_detection_enabled",0);
 0
Author: MADAO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 03:31:41