Как использовать 3G-соединение в приложении для Android вместо Wi-Fi?

Как использовать 3G-соединение в приложении для Android вместо Wi-Fi?

Я хочу подключить 3G-соединение, есть ли пример кода для подключения к 3G вместо Wi-Fi?


person Jeyavel    schedule 25.03.2010    source источник
comment
Почему бы не открыть настройки беспроводного подключения и позволить пользователю самостоятельно отключить Wi-Fi. Довольно навязчиво, но пользователь все контролирует.   -  person MrSnowflake    schedule 25.03.2010
comment
Я искал способ сделать это, но я искал слова «приоритет» (что, я думаю, было бы правильным названием для этого), а не предпочтение. Спасибо за отличный вопрос и ответ.   -  person Maarten Bodewes    schedule 03.12.2011
comment
@MrSnowflake Если вы хотите распределить нагрузку между сетевыми интерфейсами или доверяете конфиденциальной информации на одном интерфейсе и хотите направлять конфиденциальный трафик по доверенному каналу, а другой трафик по ненадежному каналу, или вы беспокоитесь, что один из интерфейсов более вероятен чтобы выпасть во время большой загрузки, или вы просто хотите дать пользователю разумные, детализированные разрешения для конкретного приложения, вы не хотите открывать страницу глобальных настроек для решения проблема, связанная с конкретным приложением.   -  person Parthian Shot    schedule 11.06.2014
comment
@MrSnowflake Что, если одно приложение всегда хочет использовать Wi-Fi, а другое приложение всегда хочет использовать мобильные данные, оба интерфейса работают, и пользователь хочет использовать оба приложения? Нет никаких технических причин, по которым оба этих приложения не могут работать, но если разработчики обоих этих приложений используют ваше решение, пользователь будет серьезно раздражен и, что, возможно, более важно, ничего полезного не произойдет.   -  person Parthian Shot    schedule 11.06.2014
comment
@ParthianShot, у вас есть действительные баллы :). Но варианты использования, которые вы указываете, являются довольно специфическими вариантами использования, я думаю, и в более общем плане приложения, вероятно, должны использовать общесистемные настройки.   -  person MrSnowflake    schedule 20.06.2014
comment
@MrSnowflake But the use cases you specify are pretty specific use cases Верно. Хотя они также являются теми вариантами использования, которые заставляют людей задавать вопросы такого типа / находить этот вопрос через Google, отсюда и упоминание.   -  person Parthian Shot    schedule 20.06.2014
comment
@ParthianShot Я согласен :).   -  person MrSnowflake    schedule 21.06.2014
comment
Все эти проблемы из-за того, что люди не знают, что такое IP. Все они очень плохие программисты. Написание сетевого кода — сложная задача, но не невозможная. Интересно, почему люди могли изучать OpenGL, но не могли изучать сокеты BSD. android.stackexchange.com/a/106182/103522   -  person Brian Cannard    schedule 22.04.2015


Ответы (9)


Приложение «Моя учетная запись» T-Mobile делает это, если вы подключены к WiFi-соединению, оно сообщает вам, что их программа не будет работать через WiFi, а затем спрашивает пользователя, хотят ли они отключить WiFi-соединение. Если вы выберете « Нет», то приложение закрывается, если вы выберете «Да», то приложение отключит ваше WiFi-соединение и затем продолжит запуск.

Я думаю, что это хорошая модель для подражания, она гарантирует, что ваше приложение не будет работать через WiFi, и позволит пользователю решать, хотят ли они отключить WiFi или нет. Улучшением этой модели было бы повторное включение Wi-Fi, когда пользователь уходит из вашего приложения.

Я не тестировал следующий код, но похоже, что он должен работать (изменено из здесь)

используйте следующие разрешения в своем манифесте

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>

и вот какой-то фактический код для включения/выключения Wi-Fi

private WifiManager wifiManager;

@Override 
public void onCreate(Bundle icicle)
{
    ....................

    wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);

    if(wifiManager.isWifiEnabled())
    {
        wifiManager.setWifiEnabled(false);
    }
    else
    {
        wifiManager.setWifiEnabled(true);
    }
}

Если вы не хотите идти по этому пути, похоже, вы можете сказать телефону, что предпочитаете использовать мобильную сеть передачи данных, а не сеть Wi-Fi.

Android ConnectivityManager предлагает функцию setNetworkPreference. Эта функция на самом деле не задокументирована, как вы можете сказать, если щелкнете по ссылке. Я бы поиграл с этим, потому что определенные константы, кажется, намекают, что вы можете установить это либо TYPE_MOBILE или TYPE_WIFI и есть константа DEFAULT_NETWORK_PREFERENCE, которая определяется как 0x00000001, что совпадает с TYPE_WIFI. Поэтому попробуйте получить доступ к ConnectivityManager, позвонив

Context.getSystemService(Context.CONNECTIVITY_SERVICE);

а затем попробуйте использовать функцию setNetworkPreference().

Похоже, что для этого не требуются какие-либо разрешения в манифесте, но может потребоваться разрешение CHANGE_NETWORK_STATE или что-то в этом роде.

Если вы подали в суд на функцию setNetworkPreference, вероятно, было бы лучше также установить настройки сети обратно в исходные значения (полученные от getNetworkPreference)

Надеюсь, это поможет.

person snctln    schedule 25.03.2010
comment
Хотя ответ ниже от @Rainbowbreeze полезен, это правильный ответ. - person Josh; 01.02.2014

/**
 * Enable mobile connection for a specific address
 * @param context a Context (application or activity)
 * @param address the address to enable
 * @return true for success, else false
 */
private boolean forceMobileConnectionForAddress(Context context, String address) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (null == connectivityManager) {
        Log.debug(TAG_LOG, "ConnectivityManager is null, cannot try to force a mobile connection");
        return false;
    }

    //check if mobile connection is available and connected
    State state = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
    Log.debug(TAG_LOG, "TYPE_MOBILE_HIPRI network state: " + state);
    if (0 == state.compareTo(State.CONNECTED) || 0 == state.compareTo(State.CONNECTING)) {
        return true;
    }

    //activate mobile connection in addition to other connection already activated
    int resultInt = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");
    Log.debug(TAG_LOG, "startUsingNetworkFeature for enableHIPRI result: " + resultInt);

    //-1 means errors
    // 0 means already enabled
    // 1 means enabled
    // other values can be returned, because this method is vendor specific
    if (-1 == resultInt) {
        Log.error(TAG_LOG, "Wrong result of startUsingNetworkFeature, maybe problems");
        return false;
    }
    if (0 == resultInt) {
        Log.debug(TAG_LOG, "No need to perform additional network settings");
        return true;
    }

    //find the host name to route
    String hostName = StringUtil.extractAddressFromUrl(address);
    Log.debug(TAG_LOG, "Source address: " + address);
    Log.debug(TAG_LOG, "Destination host address to route: " + hostName);
    if (TextUtils.isEmpty(hostName)) hostName = address;

    //create a route for the specified address
    int hostAddress = lookupHost(hostName);
    if (-1 == hostAddress) {
        Log.error(TAG_LOG, "Wrong host address transformation, result was -1");
        return false;
    }
    //wait some time needed to connection manager for waking up
    try {
        for (int counter=0; counter<30; counter++) {
            State checkState = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
            if (0 == checkState.compareTo(State.CONNECTED))
                break;
            Thread.sleep(1000);
        }
    } catch (InterruptedException e) {
        //nothing to do
    }
    boolean resultBool = connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);
    Log.debug(TAG_LOG, "requestRouteToHost result: " + resultBool);
    if (!resultBool)
        Log.error(TAG_LOG, "Wrong requestRouteToHost result: expected true, but was false");

    return resultBool;
}

И это для расчета адреса хоста:

/**
 * This method extracts from address the hostname
 * @param url eg. http://some.where.com:8080/sync
 * @return some.where.com
 */
public static String extractAddressFromUrl(String url) {
    String urlToProcess = null;

    //find protocol
    int protocolEndIndex = url.indexOf("://");
    if(protocolEndIndex>0) {
        urlToProcess = url.substring(protocolEndIndex + 3);
    } else {
        urlToProcess = url;
    }

    // If we have port number in the address we strip everything
    // after the port number
    int pos = urlToProcess.indexOf(':');
    if (pos >= 0) {
        urlToProcess = urlToProcess.substring(0, pos);
    }

    // If we have resource location in the address then we strip
    // everything after the '/'
    pos = urlToProcess.indexOf('/');
    if (pos >= 0) {
        urlToProcess = urlToProcess.substring(0, pos);
    }

    // If we have ? in the address then we strip
    // everything after the '?'
    pos = urlToProcess.indexOf('?');
    if (pos >= 0) {
        urlToProcess = urlToProcess.substring(0, pos);
    }
    return urlToProcess;
}

/**
 * Transform host name in int value used by {@link ConnectivityManager.requestRouteToHost}
 * method
 *
 * @param hostname
 * @return -1 if the host doesn't exists, elsewhere its translation
 * to an integer
 */
private static int lookupHost(String hostname) {
    InetAddress inetAddress;
    try {
        inetAddress = InetAddress.getByName(hostname);
    } catch (UnknownHostException e) {
        return -1;
    }
    byte[] addrBytes;
    int addr;
    addrBytes = inetAddress.getAddress();
    addr = ((addrBytes[3] & 0xff) << 24)
            | ((addrBytes[2] & 0xff) << 16)
            | ((addrBytes[1] & 0xff) << 8 )
            |  (addrBytes[0] & 0xff);
    return addr;
}

И следующее разрешение должно быть добавлено в AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

Он работает только с Android 2.2 и выше, протестирован как на Nexus One, так и на LG Optimus, других телефонах я не знаю, потому что некоторые методы ConnectivityMananger зависят от поставщика. Через 15-20 секунд бездействия мобильная сеть автоматически отключается.

person Rainbowbreeze    schedule 21.01.2011
comment
Я не могу проголосовать за это достаточно. Это делает именно то, что мне нужно, и работает как шарм, ничего не меняя. И это единственное хорошее решение, которое я нашел для этой проблемы во всем Интернете. - person Robber; 06.04.2013
comment
Я был немного быстр с работой, как шарм. Я должен регулярно вызывать startUsingNetworkFeature (каждые 30 секунд или около того), иначе он отключит меня, даже когда я передаю данные. Однако с этим обходным путем я еще не сталкивался с какими-либо другими проблемами. Спасибо! - person Robber; 06.04.2013
comment
в дополнение к этому отличному ответу, если кто-то хочет включить отключенное соединение для передачи данных, я предлагаю добавить вызов метода из этого ответа: stackoverflow.com/a/11555457/2347363, который можно вызвать только перед этой строкой: for (int counter=0; counter‹30; counter++) таким образом, если переключатель данных выключен, он будет работать также - person Antilope; 09.01.2015
comment
больше не работает с изменениями API в Marshmallow. см. developer.android.com/reference/android/net/, java.lang.String) - person mehmet6parmak; 23.12.2015
comment
Не анализируйте URL-адреса самостоятельно. См. java.net.URL. - person Jeffrey Blattman; 06.06.2016
comment
Вы упомянули, что через 15-20 секунд бездействия мобильная сеть автоматически отключается. Не совсем так... - person Manisha; 08.03.2017

Я думаю, что это невозможно с Java. Система отключает всю связь через мобильную сеть, если она подключена к беспроводной сети. Я думаю, что вам не разрешено запускать 3G-соединение из вашей программы.

person Janusz    schedule 25.03.2010
comment
спасибо, если мобильный пользователь включит оба средства 3G и WiFi, когда мое приложение не работает из-за того, что оно постоянно переключается с WiFi на 3G и с 3G на WiFi, можете ли вы дать какое-либо альтернативное решение - person Aswan; 25.03.2010
comment
Обойти это невозможно. Если у пользователя очень прерывистое 3G-соединение, он также будет постоянно получать сеть и терять сетевое соединение. Единственное, что вы можете сделать, это делать небольшие и частые запросы к вашему серверу и не пытаться держать соединение открытым в течение более длительного времени. А затем обработайте сетевые ошибки соответствующим образом, возможно, повторив попытку или посоветовав пользователю повторить попытку позже с более стабильным соединением. - person Janusz; 25.03.2010
comment
Мне очень жаль, но дела на Android действительно настолько плохи. Я протестировал 2 сокета BSD, один из которых был привязан к Wi-Fi, а другой — к IP-адресам 3G. Android действительно блокирует один сокет (не получает пакеты), когда переключается на другой тип сети. Если вы используете connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress); с connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");, у вас есть сокет, который вы связываете с другим адресом, получая не соответствующий ему пакет - еще хуже. - person Brian Cannard; 24.04.2015

Вот код, который работает с API 21+ (Lollipop, Marshmallow...). Я предпочитаю использовать OkHttp с Network.getSocketFactory(), но Network.openURLConnection() также работает нормально.

private void doTest()
{
    display("Requesting CELLULAR network connectivity...");
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);

    NetworkRequest request = new NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();

    connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback()
    {
        /**
         * Called when the framework connects and has declared a new network ready for use.
         * This callback may be called more than once if the {@link Network} that is
         * satisfying the request changes.
         *
         * This method will be called on non-UI thread, so beware not to use any UI updates directly.
         *
         * @param network The {@link Network} of the satisfying network.
         */
        @Override
        public void onAvailable(final Network network)
        {
            display("Got available network: " + network.toString());

            try
            {
                final InetAddress address = network.getByName("navalclash.com");
                display("Resolved host2ip: " + address.getHostName() + " -> " +  address.getHostAddress());
            }
            catch (UnknownHostException e)
            {
                e.printStackTrace();
            }

            display("Do request test page from remote http server...");

            if(okHttpClient == null)
            {
                okHttpClient = new OkHttpClient.Builder().socketFactory(network.getSocketFactory()).build();
            }

            Request request = new Request.Builder()
                    .url("http://navalclash.com")
                    .build();
            try (Response response = okHttpClient.newCall(request).execute())
            {
                display("RESULT:\n" + response.body().string());
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
    });
}
person Northern Captain    schedule 16.06.2016
comment
OkHttp, похоже, у меня не работал (что странно), но network.openURLConnection() работал. - person user1691694; 03.01.2017

Используйте диспетчер соединений и установите настройки сети по своему усмотрению.

Например:

dataManager  = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
dataManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
person Shibin Francis    schedule 05.01.2013
comment
ConnectivityManager.setNetworkPreference() почти устарел. Но что более важно, если вы сделаете getNetworkPreference() перед изменением, он вернет ConnectivityManager.TYPE_MOBILE. Установка его там не имеет никакого значения. Что касается самой HIPRI, то она работает довольно странно. Во-первых, он позволяет подключаться ко всем хостам, а не только к тем, которые явно запрошены маршрутизацией. Во-вторых, когда вы выключите его с помощью вызова stopUsingFeature...(), он не будет выключен и будет по-прежнему активен. В-третьих, его будут использовать все приложения, даже если доступен Wi-Fi, что противоречит документации. - person Cynichniy Bandera; 22.12.2013

Это приложение активирует соединение 3G и Wi-Fi, отдавая предпочтение 3G!! Очень полезно http://www.redrails.com.br/2012/02/wireless-analyzer-for-android/

person Luiz Carvalho    schedule 03.02.2012

Вдохновленный кодом в этом билете и используя некоторые его части, вот сервис, который устанавливает мобильное устройство хипри и поддерживает его работу.

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicBoolean;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo.State;
import android.os.IBinder;
import android.util.Log;

public class HipriService extends Service {
    private AtomicBoolean enabledMobile = new AtomicBoolean(false);

    public boolean enableMobileConnection() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if (null == cm) {
            Log.d(TAG, "ConnectivityManager is null, cannot try to force a mobile connection");
            return false;
        }

        /*
         * Don't do anything if we are connecting. On the other hands re-new
         * connection if we are connected.
         */
        State state = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
        Log.d(TAG, "TYPE_MOBILE_HIPRI network state: " + state);
        if (0 == state.compareTo(State.CONNECTING))
            return true;

        /*
         * Re-activate mobile connection in addition to other connection already
         * activated
         */
        int resultInt = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");
        //Log.d(TAG, "startUsingNetworkFeature for enableHIPRI result: " + resultInt);

        //-1 means errors
        // 0 means already enabled
        // 1 means enabled
        // other values can be returned, because this method is vendor specific
        if (-1 == resultInt) {
            Log.e(TAG, "Wrong result of startUsingNetworkFeature, maybe problems");
            return false;
        }
        if (0 == resultInt) {
            Log.d(TAG, "No need to perform additional network settings");
            return true;
        }

        return requestRouteToHost(this, Uploader.ServerAddress);
    }

    private Thread pingerThread = null;

    private void startMobileConnection() {
        enabledMobile.set(true);
        pingerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (enabledMobile.get()) {
                    /*
                     * Renew mobile connection. No routing setup is needed. This
                     * should be moved to 3g monitoring service one day.
                     */
                    enableMobileConnection();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // do nothing
                    }
                }
            }
        });
        pingerThread.start();
    }

    private void stopMobileConnection() {
        enabledMobile.set(false);
        disableMobileConnection();
        pingerThread.interrupt();
        pingerThread = null;
    }

    public void disableMobileConnection() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");
    }

    public final static int inetAddressToInt(InetAddress inetAddress) {
        byte[] addrBytes;
        int addr;
        addrBytes = inetAddress.getAddress();
        addr = ((addrBytes[3] & 0xff) << 24) | ((addrBytes[2] & 0xff) << 16) | ((addrBytes[1] & 0xff) << 8)
                | (addrBytes[0] & 0xff);
        return addr;
    }

    public final static InetAddress lookupHost(String hostname) {
        try {
            return InetAddress.getByName(hostname);
        } catch (UnknownHostException e) {
            return null;
        }
    }

    private boolean requestRouteToHost(Context context, String hostname) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (null == cm) {
            Log.d(TAG, "ConnectivityManager is null, cannot try to force a mobile connection");
            return false;
        }

        /* Wait some time needed to connection manager for waking up */
        try {
            for (int counter = 0; enabledMobile.get() && counter < 30; counter++) {
                State checkState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
                Log.i(TAG, "Waiting for mobile data on. State " + checkState);
                if (0 == checkState.compareTo(State.CONNECTED))
                    break;
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            //nothing to do
        }

        if (!enabledMobile.get()) {
            Log.d(TAG, "Mobile data is turned off while waiting for routing.");
            return false;
        }

        State checkState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
        if (0 != checkState.compareTo(State.CONNECTED)) {
            Log.e(TAG, "Mobile data is still turned off after 30 sec of waiting.");
            return false;
        }
        Log.i(TAG, "Adding routing for " + hostname);

        InetAddress inetAddress = lookupHost(hostname);
        if (inetAddress == null) {
            Log.e(TAG, "Failed to resolve " + hostname);
            return false;
        }
        int hostAddress = inetAddressToInt(inetAddress);

        boolean resultBool = cm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);
        Log.d(TAG, "requestRouteToHost result: " + resultBool);
        if (!resultBool)
            Log.e(TAG, "Wrong requestRouteToHost result: expected true, but was false");

        return resultBool;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        startMobileConnection();
    }

    @Override
    public void onDestroy() {
        stopMobileConnection();
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

Вот как я запускаю/останавливаю его, когда это необходимо. Обратите внимание, что он также блокирует процессор и Wi-Fi, чтобы он мог работать, когда телефон спит (только экран). Wi-Fi необходим, потому что мое приложение является своего рода мостом между Wi-Fi и мобильными соединениями. Вам это может не понадобиться.

public void startMobileData() {
    if (!enabledMobile.get()) {
        enabledMobile.set(true);
        WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, "Wifi Wakelock");
        wifiLock.acquire();

        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        partialLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "3G Wakelock");
        partialLock.acquire();

        startService(new Intent(this, HipriService.class));
    }
}

public void stopMobileData() {
    if (enabledMobile.get()) {
        enabledMobile.set(false);
        Log.i(TAG, "Disabled mobile data");
        stopService(new Intent(this, HipriService.class));

        if (partialLock != null) {
            partialLock.release();
            partialLock = null;
        }

        if (wifiLock != null) {
            wifiLock.release();
            wifiLock = null;
        }
    }
}

Не забудьте добавить службу в файл манифеста.

person Cynichniy Bandera    schedule 22.12.2013

@умка

  • я думаю, что приложение может связаться только с теми хостами через HIPRI, которые оно запросило, возможно, для других хостов (маршруты которых не запрашиваются) используется сеть по умолчанию (MOBILE или WIFI).
  • При вызове stopUsingNetworkFeature() он проверит, использует ли эту сеть какое-либо другое приложение. Если да, то он проигнорирует ваш запрос на отключение этой сетевой функции.
  • Одной из основных целей сети HIPRI является то, что если Wi-Fi включен, и приложение хочет использовать мобильную сеть (3G) для доступа к конкретному хосту, оно может подключиться через сеть HIPRI.
person simple    schedule 25.01.2014

В ответе @Northern Captain отсутствует фрагмент кода, код поиска DNS.

Вот рабочий код:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

    Log.d("NetworkDns", "Requesting CELLULAR network connectivity...");

    NetworkRequest request = new NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();

    connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback()
    {
        @Override
        public void onAvailable(final Network network)
        {
            Log.d("NetworkDns", "Got available network: " + network.toString());

            try
            {
                final InetAddress address = network.getByName("www.website.com");
                Log.d("NetworkDns", "Resolved host2ip: " + address.getHostName() + " -> " +  address.getHostAddress());
            }
            catch (UnknownHostException e)
            {
                e.printStackTrace();
            }

            Log.d("NetworkDns", "Do request test page from remote http server...");

            OkHttpClient okHttpClient = null;

            if(okHttpClient == null)
            {
                okHttpClient = new OkHttpClient.Builder()
                        .socketFactory(network.getSocketFactory())
                        .dns(new Dns() {
                            @Override
                            public List<InetAddress> lookup(String hostname) throws UnknownHostException {
                                if (network != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                                    List<InetAddress> addresses = Arrays.asList(network.getAllByName(hostname));
                                    Log.d("NetworkDns", "List : " + addresses);
                                    return addresses;
                                }
                                return SYSTEM.lookup(hostname);
                            }
                        }).build();
            }

            Request request = new Request.Builder()
                    .url("http://www.website.com")
                    .build();
            try (Response response = okHttpClient.newCall(request).execute())
            {
                Log.d("NetworkDns", "RESULT:\n" + response.body().string());
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }

        }
    });
}
person Tiago    schedule 30.05.2018