Introduction
The wifi_scan
package allows you to scan for available Wi-Fi networks and retrieve information about them in your Flutter app. This guide will show you how to integrate and use this package to scan for Wi-Fi networks in your Flutter app.
Content
1.Add the wifi_scan
dependency:
Open your pubspec.yaml
file and add the wifi_scan
dependency.
dependencies:
wifi_scan: ^latest_version
Run flutter pub get
to install the package.
2.Import the package:
Import the wifi_scan
package in your Dart file.
import 'package:wifi_scan/wifi_scan.dart';
3.Scan for Wi-Fi networks:
Use the WifiScan
class to scan for available Wi-Fi networks.
List<WifiResult> wifiList = await WifiScan().getWifiList();
This will return a list of WifiResult
objects, each containing information about a Wi-Fi network, such as SSID, BSSID, signal strength, and security type.
4.Display the Wi-Fi network information:
You can now use the scanned Wi-Fi network information in your app, such as displaying the list of networks in a ListView.
ListView.builder(
itemCount: wifiList.length,
itemBuilder: (context, index) {
WifiResult wifi = wifiList[index];
return ListTile(
title: Text(wifi.ssid),
subtitle: Text('Signal strength: ${wifi.level} dBm'),
);
},
)
5. Add permissions in AndroidManifest.xml :
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
6.Run the app:
Run your Flutter app to scan for Wi-Fi networks and display the information. You should see a list of available Wi-Fi networks along with their signal strengths.
Sample Code
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:wifi_scan/wifi_scan.dart';
void main() {
runApp(const MyApp());
}
/// Example app for wifi_scan plugin.
class MyApp extends StatefulWidget {
/// Default constructor for [MyApp] widget.
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<WiFiAccessPoint> accessPoints = <WiFiAccessPoint>[];
StreamSubscription<List<WiFiAccessPoint>>? subscription;
bool shouldCheckCan = true;
bool get isStreaming => subscription != null;
Future<void> _startScan(BuildContext context) async {
// check if "can" startScan
if (shouldCheckCan) {
// check if can-startScan
final can = await WiFiScan.instance.canStartScan();
// if can-not, then show error
if (can != CanStartScan.yes) {
if (mounted) kShowSnackBar(context, "Cannot start scan: $can");
return;
}
}
// call startScan API
final result = await WiFiScan.instance.startScan();
if (mounted) kShowSnackBar(context, "startScan: $result");
// reset access points.
setState(() => accessPoints = <WiFiAccessPoint>[]);
}
Future<bool> _canGetScannedResults(BuildContext context) async {
if (shouldCheckCan) {
// check if can-getScannedResults
final can = await WiFiScan.instance.canGetScannedResults();
// if can-not, then show error
if (can != CanGetScannedResults.yes) {
if (mounted) kShowSnackBar(context, "Cannot get scanned results: $can");
accessPoints = <WiFiAccessPoint>[];
return false;
}
}
return true;
}
Future<void> _getScannedResults(BuildContext context) async {
if (await _canGetScannedResults(context)) {
// get scanned results
final results = await WiFiScan.instance.getScannedResults();
setState(() => accessPoints = results);
}
}
Future<void> _startListeningToScanResults(BuildContext context) async {
if (await _canGetScannedResults(context)) {
subscription = WiFiScan.instance.onScannedResultsAvailable.listen((result) => setState(() => accessPoints = result));
}
}
void _stopListeningToScanResults() {
subscription?.cancel();
setState(() => subscription = null);
}
@override
void dispose() {
super.dispose();
// stop subscription for scanned results
_stopListeningToScanResults();
}
// build toggle with label
Widget _buildToggle({
String? label,
bool value = false,
ValueChanged<bool>? onChanged,
Color? activeColor,
}) =>
Row(
children: [
if (label != null) Text(label),
Switch(value: value, onChanged: onChanged, activeColor: activeColor),
],
);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Wifi Scan View'),
actions: [
_buildToggle(label: "Check can?", value: shouldCheckCan, onChanged: (v) => setState(() => shouldCheckCan = v), activeColor: Colors.purple)
],
),
body: Builder(
builder: (context) => Padding(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
icon: const Icon(Icons.perm_scan_wifi),
label: const Text('SCAN'),
onPressed: () async => _startScan(context),
),
ElevatedButton.icon(
icon: const Icon(Icons.refresh),
label: const Text('GET'),
onPressed: () async => _getScannedResults(context),
),
_buildToggle(
label: "STREAM",
value: isStreaming,
onChanged: (shouldStream) async => shouldStream ? await _startListeningToScanResults(context) : _stopListeningToScanResults(),
),
],
),
const Divider(),
Flexible(
child: Center(
child: accessPoints.isEmpty
? const Text("NO SCANNED RESULTS")
: ListView.builder(
itemCount: accessPoints.length, itemBuilder: (context, i) => _AccessPointTile(accessPoint: accessPoints[i])),
),
),
],
),
),
),
),
);
}
}
/// Show tile for AccessPoint.
///
/// Can see details when tapped.
class _AccessPointTile extends StatelessWidget {
final WiFiAccessPoint accessPoint;
const _AccessPointTile({Key? key, required this.accessPoint}) : super(key: key);
// build row that can display info, based on label: value pair.
Widget _buildInfo(String label, dynamic value) => Container(
decoration: const BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.grey)),
),
child: Row(
children: [
Text(
"$label: ",
style: const TextStyle(fontWeight: FontWeight.bold),
),
Expanded(child: Text(value.toString()))
],
),
);
@override
Widget build(BuildContext context) {
final title = accessPoint.ssid.isNotEmpty ? accessPoint.ssid : "**EMPTY**";
final signalIcon = accessPoint.level >= -80 ? Icons.signal_wifi_4_bar : Icons.signal_wifi_0_bar;
return ListTile(
visualDensity: VisualDensity.compact,
leading: Icon(signalIcon),
title: Text(title),
subtitle: Text(accessPoint.capabilities),
onTap: () => showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(title),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildInfo("BSSDI", accessPoint.bssid),
_buildInfo("Capability", accessPoint.capabilities),
_buildInfo("frequency", "${accessPoint.frequency}MHz"),
_buildInfo("level", accessPoint.level),
_buildInfo("standard", accessPoint.standard),
_buildInfo("centerFrequency0", "${accessPoint.centerFrequency0}MHz"),
_buildInfo("centerFrequency1", "${accessPoint.centerFrequency1}MHz"),
_buildInfo("channelWidth", accessPoint.channelWidth),
_buildInfo("isPasspoint", accessPoint.isPasspoint),
_buildInfo("operatorFriendlyName", accessPoint.operatorFriendlyName),
_buildInfo("venueName", accessPoint.venueName),
_buildInfo("is80211mcResponder", accessPoint.is80211mcResponder),
],
),
),
),
);
}
}
/// Show snackbar.
void kShowSnackBar(BuildContext context, String message) {
if (kDebugMode) print(message);
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(message)));
}
Output
Conclusion
By following these steps, you can easily integrate the wifi_scan
package into your Flutter app and scan for available Wi-Fi networks. This can be useful for apps that require Wi-Fi network information, such as network analyzers or Wi-Fi management apps.