codestory

Die Anleitung zu Android Wifi Scanning

  1. Android Wi-Fi
  2. Beispiel von WifiManager

1. Android Wi-Fi

In Android ist Wi-Fi als Wireless Network Protocol bezeichnet. Es möglicht die Geräten, eine Verbindung zum Internet herzustellen oder die Geräten, die zum Datenaustausch miteinander verbunden sind.
Insbesondere bietet Android die Wi-Fi API, mit der Anwendungen die API verwenden können, um alle Aspekte der Wifi-Connection zu verwalten, z.B das Suchen nach aktuellen Wifi Networks, das Hinzufügen, Speichern, Löschen von Wifi-Connection sowie das Verwalten von Daten, die zwischen Geräten ausgetauscht werden.
Mit der Verwendung von Wi-Fi API in Ihrer Anwendung können Sie die folgenden Funktionen durchführen:
  • Scannen, um nach verfügbaren Wifi-Netwerken in einem Bereich zu suchen.
  • Ermöglichen Sie Geräten, eine Verbindung zum Internet herzustellen.
  • Verbinden Sie durch Service Discovery zu anderen Geräten.
  • Verwalten Sie eine Liste der konfigurierten Netwerke.
  • Verwalten Sie mehrere Verbindungen.
Seit Android 10.0 (API Level 29) können Sie die Wi-Fi API nicht mehr verwenden, um das Wifi des Systems zu aktivieren/deaktivieren. Dies bedeutet, dass Sie die verfügbare Funktion des Betriebssystem verwenden müssen wenn Sie Wifi aktivieren/deaktivieren möchten.
Die Datenschutzrichtlinie für die Verwendung der Wi-Fi API zum Aktivieren/Deaktivieren von Wifi wurde in verschiedenen Android-Versionen einige Male geändert. Konkret ist es:
Android Level
Datenschutz-Bestimmung
Level 1 ==> Level 22
(Android < 6.0)
android.permission.CHANGE_WIFI_STATE muss zu AndroidManifest.xml hinzugefügt werden.
Level 23 ==> Level 28
(Android 6.0 - 9.x)
android.permission.CHANGE_WIFI_STATE muss zu AndroidManifest.xml hinzugefügt werden. Gleichzeitig muss die Anwendung den Benutzer auffordern, das Aktivieren/Deaktiveren des Wifi des Systems zuzulassen.
Level 29+
(Android 10.0+)
Wi-Fi API darf Wifi vom System nicht aktivieren/deaktivieren.
* AndroidManifest.xml *
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);

wifiManager.setWifiEnabled(true); // Enable Wifi

wifiManager.setWifiEnabled(false); // Disable Wifi
In Android 10+ (API Level 29+) wird das Methode setWifiEnabled(boolean) nicht mehr verwendet.
Um den Wifi Status zu erhalten, müssen Sie android.permission.ACCESS_WIFI_STATE zu AndroidManifest.xml hinzufügen:
* AndroidManifest.xml *
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
int state = wifiManager.getWifiState();
String statusInfo = "Unknown";

switch (state)  {
    case WifiManager.WIFI_STATE_DISABLING:
        statusInfo = "Disabling";
        break;
    case WifiManager.WIFI_STATE_DISABLED:
        statusInfo = "Disabled";
        break;
    case WifiManager.WIFI_STATE_ENABLING:
        statusInfo = "Enabling";
        break;
    case WifiManager.WIFI_STATE_ENABLED:
        statusInfo = "Enabled";
        break;
    case WifiManager.WIFI_STATE_UNKNOWN:
        statusInfo = "Unknown";
        break;
    default:
        statusInfo = "Unknown";
        break;
}
Scannen Sie um nach den aktuellen Netzwerken zu suchen:
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
// Get List of Available Wifi Networks
List<ScanResult> availNetworks = wifiManager.getScanResults();

if (availNetworks.size() > 0) {
    
    // Get Each network detail
    for (int i=0; i< availNetworks.size();i++) {
        // ...
    }
}
Die Datenschutzrichtlinie zum Scannen der aktuellen Netzwerk wurde einige Male auf verschiedene Android Versionen geändert:
Android API Level
Datenschutz-Bestimmung
Level 1 ==> Level 22
(Android < 6.0)
android.permission.ACCESS_COARSE_LOCATION muss zu AndroidManifest.xml hinzugefügt werden.
Level 23+
(Android 6.0+)
android.permission.ACCESS_COARSE_LOCATION muss zu AndroidManifest.xml hinzugefügt werden. Gleichzeitig muss Ihre Anwendung den Benutzer auffordern, das Scannen der aktuellen Netwerk zuzulassen.
* AndroidManifest.xml *
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  • Die Anleitung zu Android Wifi Direct P2P

2. Beispiel von WifiManager

In diesem Beispiel werde ich Sie anleiten, wie Sie mit WifiManager den Status des Wifi abrufen, die aktuellen Netzwerke scannen, die Details jedes gefundenen Netzwerks notieren und eine Verbindung zu einem bestimmten Netwerk in die Liste herstellen.
Das Beispiel Vorschau
Auf Android Studio erstellen Sie ein neues Projekt:
  • File > New > New Project > Empty Activity
    • Name: WifiManagerExample
    • Package name: org.o7planning.wifimanagerexample
    • Language: Java
Anschließend fügen Sie die Anwendung die Berechtigungen hinzu:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.o7planning.wifimanagerexample">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Und hier ist die Interface der Beispiel-Anwendung:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button_state"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:text="Show Wifi State"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button_scan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:text="Scan Wifi"
        app:layout_constraintStart_toEndOf="@+id/button_state"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText_password"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="12345678"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button_state" />

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="0dp"
        android:layout_height="143dp"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:background="#F3F4EB"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText_password">

        <LinearLayout
            android:id="@+id/linearLayout_scanResults"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5sp"
            android:layout_marginTop="5sp"
            android:layout_marginRight="5sp"
            android:layout_marginBottom="5sp"
            android:orientation="vertical" />
    </ScrollView>

    <TextView
        android:id="@+id/textView_scanResults"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="16dp"
        android:background="#F1F3E7"
        android:inputType="textMultiLine"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/scrollView" />

</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package org.o7planning.wifimanagerexample;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final String LOG_TAG = "AndroidExample";

    private static final int MY_REQUEST_CODE = 123;

    private WifiManager wifiManager;

    private Button buttonState;
    private Button buttonScan;

    private EditText editTextPassword;
    private LinearLayout linearLayoutScanResults;
    private TextView textViewScanResults;

    private WifiBroadcastReceiver wifiReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

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

        // Instantiate broadcast receiver
        this.wifiReceiver = new WifiBroadcastReceiver();

        // Register the receiver
        registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

        //
        this.buttonState = (Button) this.findViewById(R.id.button_state);
        this.buttonScan = (Button) this.findViewById(R.id.button_scan);

        this.editTextPassword = (EditText) this.findViewById(R.id.editText_password);
        this.textViewScanResults = (TextView) this.findViewById(R.id.textView_scanResults);
        this.linearLayoutScanResults = (LinearLayout) this.findViewById(R.id.linearLayout_scanResults);

        this.buttonState.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                showWifiState();
            }
        });

        this.buttonScan.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                askAndStartScanWifi();
            }
        });
    }


    private void askAndStartScanWifi()  {

        // With Android Level >= 23, you have to ask the user
        // for permission to Call.
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { // 23
            int permission1 = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);

            // Check for permissions
            if (permission1 != PackageManager.PERMISSION_GRANTED) {

                Log.d(LOG_TAG, "Requesting Permissions");

                // Request permissions
                ActivityCompat.requestPermissions(this,
                        new String[] {
                                Manifest.permission.ACCESS_COARSE_LOCATION,
                                Manifest.permission.ACCESS_FINE_LOCATION,
                                Manifest.permission.ACCESS_WIFI_STATE,
                                Manifest.permission.ACCESS_NETWORK_STATE
                        }, MY_REQUEST_CODE);
                return;
            }
            Log.d(LOG_TAG, "Permissions Already Granted");
        }
        this.doStartScanWifi();
    }

    private void doStartScanWifi()  {
        this.wifiManager.startScan();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)  {
        Log.d(LOG_TAG, "onRequestPermissionsResult");

        switch (requestCode)  {
            case MY_REQUEST_CODE:  {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)  {
                    // permission was granted
                    Log.d(LOG_TAG, "Permission Granted: " + permissions[0]);

                    // Start Scan Wifi.
                    this.doStartScanWifi();
                }  else   {
                    // Permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Log.d(LOG_TAG, "Permission Denied: " + permissions[0]);
                }
                break;
            }
            // Other 'case' lines to check for other
            // permissions this app might request.
        }
    }

    private void showWifiState()  {
        int state = this.wifiManager.getWifiState();
        String statusInfo = "Unknown";

        switch (state)  {
            case WifiManager.WIFI_STATE_DISABLING:
                statusInfo = "Disabling";
                break;
            case WifiManager.WIFI_STATE_DISABLED:
                statusInfo = "Disabled";
                break;
            case WifiManager.WIFI_STATE_ENABLING:
                statusInfo = "Enabling";
                break;
            case WifiManager.WIFI_STATE_ENABLED:
                statusInfo = "Enabled";
                break;
            case WifiManager.WIFI_STATE_UNKNOWN:
                statusInfo = "Unknown";
                break;
            default:
                statusInfo = "Unknown";
                break;
        }
        Toast.makeText(this, "Wifi Status: " + statusInfo, Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onStop()  {
        this.unregisterReceiver(this.wifiReceiver);
        super.onStop();
    }


    // Define class to listen to broadcasts
    class WifiBroadcastReceiver extends BroadcastReceiver  {
        @Override
        public void onReceive(Context context, Intent intent)   {
            Log.d(LOG_TAG, "onReceive()");

            Toast.makeText(MainActivity.this, "Scan Complete!", Toast.LENGTH_SHORT).show();

            boolean ok = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);

            if (ok)  {
                Log.d(LOG_TAG, "Scan OK");

                List<ScanResult> list = wifiManager.getScanResults();

                MainActivity.this.showNetworks(list);
                MainActivity.this.showNetworksDetails(list);
            }  else {
                Log.d(LOG_TAG, "Scan not OK");
            }

        }
    }

    private void showNetworks(List<ScanResult> results) {
        this.linearLayoutScanResults.removeAllViews();

        for( final ScanResult result: results)  {
            final String networkCapabilities = result.capabilities;
            final String networkSSID = result.SSID; // Network Name.
            //
            Button button = new Button(this );

            button.setText(networkSSID + " ("+networkCapabilities+")");
            this.linearLayoutScanResults.addView(button);

            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String networkCapabilities = result.capabilities;
                    connectToNetwork(networkCapabilities, networkSSID);
                }
            });
        }
    }

    private void showNetworksDetails(List<ScanResult> results)  {

        this.textViewScanResults.setText("");
        StringBuilder sb = new StringBuilder();
        sb.append("Result Count: " + results.size());

        for(int i = 0; i < results.size(); i++ )  {
            ScanResult result = results.get(i);
            sb.append("\n\n  --------- Network " + i + "/" + results.size() + " ---------");

            sb.append("\n result.capabilities: " + result.capabilities);
            sb.append("\n result.SSID: " + result.SSID); // Network Name.

            sb.append("\n result.BSSID: " + result.BSSID);
            sb.append("\n result.frequency: " + result.frequency);
            sb.append("\n result.level: " + result.level);

            sb.append("\n result.describeContents(): " + result.describeContents());

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // Level 17, Android 4.2
                sb.append("\n result.timestamp: " + result.timestamp);
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Level 23, Android 6.0
                sb.append("\n result.centerFreq0: " + result.centerFreq0);
                sb.append("\n result.centerFreq1: " + result.centerFreq1);
                sb.append("\n result.venueName: " + result.venueName);
                sb.append("\n result.operatorFriendlyName: " + result.operatorFriendlyName);
                sb.append("\n result.channelWidth: " + result.channelWidth);
                sb.append("\n result.is80211mcResponder(): " + result.is80211mcResponder());
                sb.append("\n result.isPasspointNetwork(): " + result.isPasspointNetwork() );
            }
        }
        this.textViewScanResults.setText(sb.toString());
    }

    private void connectToNetwork(String networkCapabilities, String networkSSID)  {
        Toast.makeText(this, "Connecting to network: "+ networkSSID, Toast.LENGTH_SHORT).show();

        String networkPass = this.editTextPassword.getText().toString();
        //
        WifiConfiguration wifiConfig = new WifiConfiguration();
        wifiConfig.SSID =  "\"" + networkSSID + "\"";

        if(networkCapabilities.toUpperCase().contains("WEP")) { // WEP Network.
            Toast.makeText(this, "WEP Network", Toast.LENGTH_SHORT).show();

            wifiConfig.wepKeys[0] = "\"" + networkPass + "\"";
            wifiConfig.wepTxKeyIndex = 0;
            wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        } else if(networkCapabilities.toUpperCase().contains("WPA")) { // WPA Network
            Toast.makeText(this, "WPA Network", Toast.LENGTH_SHORT).show();
            wifiConfig.preSharedKey = "\""+ networkPass +"\"";
        } else  { // OPEN Network.
            Toast.makeText(this, "OPEN Network", Toast.LENGTH_SHORT).show();
            wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        }

        this.wifiManager.addNetwork(wifiConfig);

        List<WifiConfiguration> list = this.wifiManager.getConfiguredNetworks();
        for( WifiConfiguration config : list ) {
            if(config.SSID != null && config.SSID.equals("\"" + networkSSID + "\"")) {
                this.wifiManager.disconnect();
                this. wifiManager.enableNetwork(config.networkId, true);
                this.wifiManager.reconnect();
                break;
            }
        }
    }
}

Anleitungen Android

Show More