wake-up-neo.net

Erzwingen, dass Android das WLAN-Netzwerk ohne Internet verwendet

Ich baue eine Android-App, die über ein WLAN-Netzwerk kommunizieren muss, das keinen Internetzugang hat. Das Problem ist, dass Android auch dann eine Verbindung zwischen WLAN und Mobilfunk herstellt, wenn im Internet keine Internetverbindung besteht.

Ich habe viele Beiträge zu diesem Thema gelesen, von denen viele das Rooten des Geräts betreffen, aber dies ist mit einer Produktions-App nicht möglich (das Rooten von Geräten ist nicht eine Option). Eine andere Lösung (wie mein Code unten) schlägt die Verwendung von bindProcessToNetwork() vor, die auf meiner Sony Z2 einwandfrei funktioniert, jedoch nicht auf anderen Geräten, auf denen ich getestet habe (alle 6.0.1).

private void bindToNetwork() {
    final ConnectivityManager connectivityManager = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest.Builder builder;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        builder = new NetworkRequest.Builder();
        //set the transport type do WIFI
        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


                    connectivityManager.bindProcessToNetwork(null);
                    if (barCodeData.getSsid().contains("screenspace")) {
                        connectivityManager.bindProcessToNetwork(network);
                    }

                } else {
                    //This method was deprecated in API level 23
                    ConnectivityManager.setProcessDefaultNetwork(null);
                    if (barCodeData.getSsid().contains("screenspace")) {

                        ConnectivityManager.setProcessDefaultNetwork(network);
                    }
                }

                connectivityManager.unregisterNetworkCallback(this);
            }
        });
    }
}
25
Lonergan6275

Könnten Sie versuchen, die globale Einstellung captive_portal_detection_enabled auf 0 (false) zu setzen.

Tatsächlich geschieht Folgendes: Standardmäßig testet die FW jedes Mal, wenn Sie eine Verbindung zu einem WLAN herstellen, anhand eines Servers (in der Regel Google), ob es sich um ein firmeneigenes WLAN handelt (Anmeldung erforderlich). Wenn Ihr WLAN nicht mit Google verbunden ist, schlägt diese Überprüfung fehl. Danach weiß das Gerät, dass WLAN keine Internetverbindung hat und stellt einfach keine automatische Verbindung her.

Wenn Sie diese Einstellung auf 0 setzen, wird diese Überprüfung vermieden.

Programmatisch: Settings.Global.putInt(getContentResolver(), Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 0);

Bearbeiten: Möglicherweise müssen Sie die Zeichenfolge "captive_portal_detection_enabled" direkt anstelle der Konstante verwenden, die je nach Version von Android) nicht sichtbar ist.

2
lax1089

Sie können prüfen, ob eine WLAN-Verbindung besteht. Fahren Sie ansonsten fort und zeigen Sie dem Benutzer ein Dialogfeld an, in dem Sie aufgefordert werden, eine Verbindung zu einem WLAN-Netzwerk herzustellen

Da die Methode NetworkInfo.isConnected () in API-23 nun veraltet ist, wird hier eine Methode ermittelt, die erkennt, ob der Wi-Fi-Adapter eingeschaltet ist und stattdessen auch über WifiManager mit einem Zugriffspunkt verbunden ist:

private boolean checkWifiOnAndConnected() {
    WifiManager wifiMgr = (WifiManager) getSystemService(Context.WIFI_SERVICE);

    if (wifiMgr.isWifiEnabled()) { // Wi-Fi adapter is ON

        WifiInfo wifiInfo = wifiMgr.getConnectionInfo();

        if( wifiInfo.getNetworkId() == -1 ){
            return false; // Not connected to an access point
        }
        return true; // Connected to an access point
    }
    else {
        return false; // Wi-Fi adapter is OFF
    }
}
1
Akshay Sood

sie müssten mobile Daten in den Einstellungen deaktivieren (nicht sicher, ob dies programmgesteuert möglich ist, was eine mögliche Option sein kann) - oder die USIM entfernen.

ansonsten ist es üblich, dass immer auf die beste verfügbare Verbindung zurückgegriffen wird (während eine Verbindung mit einem Internet-Gateway bevorzugt werden kann, da sie von den meisten Anwendungen verwendet wird).

siehe auch diese Antwort .

1
Martin Zeitler

Sie sind auf dem richtigen Weg, die Lösung ist in der Tat mit ConnectivityManager.bindProcessToNetwork (Netzwerk) . Diese Informationen wurden im Android Developers Blog in diesem Artikel veröffentlicht: Anschließen einer App an ein Wi-Fi-Gerät .

Wenn Sie in Ihren Code schauen, sieht diese barCodeData.getSsid() nicht so aus, dass sie die SSID des aktuell verbundenen WLAN-Netzwerks erhält. In diesem Fall wird Ihr Code niemals erfolgreich an das Netzwerk gebunden.

Versuchen Sie, Ihre if-Anweisung zu ersetzen.

if (barCodeData.getSsid().contains("screenspace"))

Mit

if (getNetworkSsid(context).equals("screenspace"))

Hilfsmethode in kotlin zum Abrufen der SSID des verbundenen WLAN-Netzwerks

private fun getNetworkSsid(context: Context?): String {
    // WiFiManager must use application context (not activity context) otherwise a memory leak can occur
    val mWifiManager = context?.applicationContext?.getSystemService(Context.WIFI_SERVICE) as WifiManager
    val wifiInfo: WifiInfo? = mWifiManager.connectionInfo
    if (wifiInfo?.supplicantState == SupplicantState.COMPLETED) {
        return wifiInfo.ssid.removeSurrounding("\"")
    }
    return ""
}

Wenn immer noch nicht funktioniert, folgen Sie bitte meiner vollständigen Lösung , bei der ich dieselbe Methode verwendet habe, jedoch mit einigen zusätzlichen Prüfungen. Ich habe es in den Android-Versionen 5.1.1, 6.0, 6.0.1, 7.1.1 und 8.1.0 getestet.

0
Ryan Amaral

Lösung auf Kotlin

class ConnectWithoutInternetTest constructor(
private val mContext: Context,
private val connectivityManager: ConnectivityManager,
private val wifiManager: WifiManager
) {

private val mWifiBroadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            WifiManager.NETWORK_STATE_CHANGED_ACTION -> {
                val info = intent.getParcelableExtra<NetworkInfo>(WifiManager.EXTRA_NETWORK_INFO)
                val isConnected = info.isConnected

                val ssid: String? = normalizeAndroidWifiSsid(wifiManager.connectionInfo?.ssid)

                if (isConnected) {
                    val builder = NetworkRequest.Builder()
                    builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    connectivityManager.registerNetworkCallback(
                        builder.build(),
                        object : ConnectivityManager.NetworkCallback() {
                            override fun onAvailable(network: Network) {
                                super.onAvailable(network)
                                val networkInfo = connectivityManager.getNetworkInfo(network)
                                val networkSsid = networkInfo.extraInfo
                                if (networkSsid == ssid) {
                                    connectivityManager.unregisterNetworkCallback(this)
                                }
                            }
                        })
                }
            }
        }
    }
}

private fun init() {
    val intentFilter = IntentFilter()
    intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
    mContext.registerReceiver(mWifiBroadcastReceiver, intentFilter)
}

private fun destroy() {
    mContext.unregisterReceiver(mWifiBroadcastReceiver)
}

private fun normalizeAndroidWifiSsid(ssid: String?): String? {
    return ssid?.replace("\"", "") ?: ssid
}

fun connectToWifi(ssidParam: String, password: String?) {
    init()
    val ssid = "\"$ssidParam\""
    val config = wifiManager.configuredNetworks.find { it.SSID == ssid }
    val netId = if (config != null) {
        config.networkId
    } else {
        val wifiConfig = WifiConfiguration()
        wifiConfig.SSID = ssid
        password?.let { wifiConfig.preSharedKey = "\"$password\"" }
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
        wifiManager.addNetwork(wifiConfig)
    }

    wifiManager.disconnect()
    val successful = wifiManager.enableNetwork(netId, true)
}
0
Vados