Connect to Wifi through your capacitor plugin. Good for IoT device connections.
npm install @tolutronics/capacitor-wifiA powerful Capacitor plugin for WiFi management with real-time monitoring capabilities. Perfect for IoT device connections, network provisioning, and WiFi state management in mobile applications.
This is a custom-built Capacitor plugin developed specifically for advanced WiFi management needs. While inspired by community WiFi plugins, this implementation was created from scratch to address specific requirements for:
- IoT Device Setup Workflows: Seamless connection to devices with dynamic or prefix-based SSIDs
- Real-time Network Monitoring: Event-driven architecture for WiFi connection state changes
- Enterprise WiFi Management: Comprehensive network configuration and control
- Cross-platform Reliability: Native implementations for both iOS and Android with consistent APIs
Existing community WiFi plugins either lacked real-time monitoring, didn't support prefix-based SSID matching (crucial for IoT), or had limited connection management features. This plugin was built to fill those gaps with:
- ✅ Complete disconnect control - Separate methods for temporary disconnect vs. forget network
- ✅ Real-time event monitoring - Track connection state changes as they happen
- ✅ IoT-first design - Prefix matching for devices with dynamic SSIDs
- ✅ Modern architecture - Built for Capacitor 6+ with TypeScript-first approach
- ✅ Production-ready - Extensively tested with real IoT devices and enterprise networks
- 📶 WiFi Network Scanning - Discover available networks with signal strength and security info
- 🔗 Smart Connection Management - Connect by exact SSID or prefix matching (perfect for IoT devices)
- ⚡ Real-time Event Monitoring - Get notified of connection/disconnection events instantly
- 🛡️ Permission Handling - Seamless location and network permission management
- 📱 Cross-Platform - Native iOS and Android implementations
- 🔌 IoT Device Support - Specialized features for connecting to IoT devices with dynamic SSIDs
> ⚠️ Platform Support: This plugin only works on native iOS and Android platforms. WiFi operations are not available in web browsers due to security restrictions.
#### Real-time WiFi Connection Monitoring
- Event-driven architecture: Get notified instantly when WiFi connects, disconnects, or switches networks
- Connection history tracking: Monitor connection patterns and handle network transitions
- Automatic state updates: Keep your UI in sync with actual WiFi state
#### Enhanced Disconnect Control
- disconnect() method: Temporarily disconnect while keeping network saved for auto-reconnect
- disconnectAndForget() method: Completely remove network from device's saved networks
- Smart network management: Choose the right disconnect strategy for your use case
#### IoT Device Support
- Prefix-based connection: connectToWifiBySsidPrefixAndPassword() for devices with dynamic SSIDs
- Device discovery: Find and connect to IoT devices with predictable SSID patterns
- Setup flow optimization: Perfect for camera, sensor, and smart home device provisioning
- v1.0.0 (Initial Release)
- Basic WiFi scanning and connection
- Permission management
- iOS and Android native implementations
- v1.1.0 (Connection Events)
- Added wifiConnectionChange event listener
- Real-time connection state monitoring
- Connection history tracking
- v1.2.0 (Disconnect Control)
- Added disconnect() for temporary disconnection
- Enhanced disconnectAndForget() for complete removal
- Platform-specific disconnect behavior documentation
- v1.3.0 (Documentation & Examples)
- Comprehensive usage examples
- React, Angular, and Vue component examples
- IoT device setup workflows
- Collapsible sections for better navigation
``bash`
npm install @tolutronics/capacitor-wifi
npx cap sync
`typescript
import { Wifi } from '@tolutronics/capacitor-wifi';
// Scan for networks
const { wifis } = await Wifi.scanWifi();
// Connect to a network
await Wifi.connectToWifiBySsidAndPassword({
ssid: 'MyNetwork',
password: 'password123'
});
// Monitor connection changes
const listener = await Wifi.addListener('wifiConnectionChange', (event) => {
console.log('WiFi state:', event.isConnected ? 'Connected' : 'Disconnected');
});
`
| Method | Description |
|--------|-------------|
| scanWifi() | Scan for available WiFi networks |getCurrentWifi()
| | Get current connected network info |connectToWifiBySsidAndPassword()
| | Connect to network by exact SSID |connectToWifiBySsidPrefixAndPassword()
| | Connect to network by SSID prefix (IoT devices) |addListener('wifiConnectionChange', callback)
| | Monitor WiFi connection changes |checkPermissions()
| / requestPermissions() | Handle WiFi and location permissions |disconnect()
| | Disconnect from current network (keeps network saved) |disconnectAndForget()
| | Disconnect and remove network from saved networks |
- 📱 Mobile App WiFi Management - Let users connect to networks within your app
- 🏠 Smart Home Setup - Connect users to IoT devices during setup flows
- 🏭 Industrial IoT - Provision devices with dynamic or prefix-based SSIDs
- 📊 Network Monitoring - Track WiFi connectivity for analytics or UX
- 🔄 Automatic Reconnection - Handle network switching and failover scenarios
Basic Setup
`typescript
import { Wifi } from '@tolutronics/capacitor-wifi';
import { Capacitor } from '@capacitor/core';
// Platform check helper
const isNativePlatform = () => {
return Capacitor.isNativePlatform();
};
// Check and request permissions first
const checkWifiPermissions = async () => {
if (!isNativePlatform()) {
console.warn('WiFi operations are only available on native platforms');
return false;
}
const status = await Wifi.checkPermissions();
if (status.LOCATION !== 'granted' || status.NETWORK !== 'granted') {
const result = await Wifi.requestPermissions();
return result.LOCATION === 'granted' && result.NETWORK === 'granted';
}
return true;
};
`
Scanning for WiFi Networks
`typescript
const scanForNetworks = async () => {
try {
const hasPermissions = await checkWifiPermissions();
if (!hasPermissions) {
console.error('WiFi permissions not granted');
return;
}
const result = await Wifi.scanWifi();
console.log('Available networks:', result.wifis);
// Display networks to user
result.wifis.forEach(wifi => {
console.log(SSID: ${wifi.ssid}, Signal: ${wifi.level}, Current: ${wifi.isCurrentWifi});`
});
} catch (error) {
console.error('Failed to scan WiFi:', error);
}
};
Connecting to WiFi Networks
`typescript
// Connect to a specific network
const connectToWifi = async (ssid: string, password: string) => {
try {
const result = await Wifi.connectToWifiBySsidAndPassword({
ssid,
password
});
if (result.wasSuccess) {
console.log('Connected successfully!', result.wifi);
}
} catch (error) {
console.error('Failed to connect:', error);
}
};
// Connect to IoT device by SSID prefix (useful for devices with dynamic names)
const connectToIoTDevice = async (devicePrefix: string, password: string) => {
try {
const result = await Wifi.connectToWifiBySsidPrefixAndPassword({
ssidPrefix: devicePrefix, // e.g., "MyCamera_"
password
});
if (result.wasSuccess) {
console.log('Connected to IoT device!', result.wifi);
}
} catch (error) {
console.error('Failed to connect to IoT device:', error);
}
};
`
Getting Current WiFi Information
`typescript
const getCurrentNetwork = async () => {
try {
const result = await Wifi.getCurrentWifi();
if (result.currentWifi) {
console.log('Current WiFi:', {
ssid: result.currentWifi.ssid,
bssid: result.currentWifi.bssid,
signal: result.currentWifi.level
});
} else {
console.log('Not connected to any WiFi network');
}
} catch (error) {
console.error('Failed to get current WiFi:', error);
}
};
`
Complete IoT Setup Flow
`typescript
const setupIoTDevice = async (devicePrefix: string, devicePassword: string) => {
try {
// 1. Check permissions
const hasPermissions = await checkWifiPermissions();
if (!hasPermissions) {
throw new Error('WiFi permissions required');
}
// 2. Get current WiFi (to restore later if needed)
const currentWifi = await Wifi.getCurrentWifi();
console.log('Current network:', currentWifi.currentWifi?.ssid);
// 3. Scan for available networks
const scanResult = await Wifi.scanWifi();
const deviceNetworks = scanResult.wifis.filter(wifi =>
wifi.ssid.startsWith(devicePrefix)
);
if (deviceNetworks.length === 0) {
throw new Error(No devices found with prefix: ${devicePrefix});
}
console.log(Found ${deviceNetworks.length} device(s));
// 4. Connect to device
const connectResult = await Wifi.connectToWifiBySsidPrefixAndPassword({
ssidPrefix: devicePrefix,
password: devicePassword
});
if (!connectResult.wasSuccess) {
throw new Error('Failed to connect to device');
}
console.log('Successfully connected to device:', connectResult.wifi?.ssid);
// 5. Perform device configuration here
// ... your device setup logic ...
// 6. Disconnect from device (keeping it saved for future connections)
// await Wifi.disconnect();
// OR completely remove the device network from saved networks
// await Wifi.disconnectAndForget();
} catch (error) {
console.error('IoT setup failed:', error);
}
};
// Usage
setupIoTDevice('MyCamera_', 'device123');
`
Disconnecting from WiFi Networks
The plugin provides two different disconnect methods with distinct behaviors:
#### disconnect() - Disconnect but Keep Network Saved`typescriptDisconnecting from: ${currentResult.currentWifi.ssid}
const disconnectTemporarily = async () => {
try {
// Get current network info before disconnecting
const currentResult = await Wifi.getCurrentWifi();
if (currentResult.currentWifi) {
console.log();
// Disconnect but keep the network configuration saved
await Wifi.disconnect();
console.log('Disconnected - network configuration preserved');
// The device can automatically reconnect to this network later
// without requiring the password again
}
} catch (error) {
console.error('Failed to disconnect:', error);
}
};
`
#### disconnectAndForget() - Disconnect and Remove Network`typescriptRemoving network: ${currentResult.currentWifi.ssid}
const disconnectPermanently = async () => {
try {
const currentResult = await Wifi.getCurrentWifi();
if (currentResult.currentWifi) {
console.log();
// Disconnect and completely remove network from device
await Wifi.disconnectAndForget();
console.log('Network removed from saved networks');
// To reconnect later, user will need to enter password again
}
} catch (error) {
console.error('Failed to disconnect and forget:', error);
}
};
`
#### When to Use Each Method
Use disconnect() when:
- Testing network configurations temporarily
- Switching between networks programmatically
- Implementing network failover scenarios
- You want the device to auto-reconnect later
- Working with trusted networks that should remain saved
Use disconnectAndForget() when:
- Removing untrusted or temporary networks
- Cleaning up after IoT device configuration
- Implementing a "forget network" feature for users
- Security requires complete removal of network credentials
- Working with one-time setup networks
#### Platform Behavior Differences
Android:
- disconnect(): Disables current network but preserves configurationdisconnectAndForget()
- : Removes network from saved networks entirelydisconnect()
- Device can auto-reconnect to networks disconnected with
iOS:
- disconnect(): Limited functionality due to iOS restrictionsdisconnectAndForget()
- : Standard iOS behavior for removing network configurations
- iOS doesn't support true "disconnect without forgetting" due to platform limitations
`typescript
// Example: Smart network management
const smartDisconnect = async (networkSsid: string, shouldForget: boolean = false) => {
try {
const current = await Wifi.getCurrentWifi();
if (current.currentWifi?.ssid === networkSsid) {
if (shouldForget) {
console.log(Removing ${networkSsid} permanently);Disconnecting from ${networkSsid} temporarily
await Wifi.disconnectAndForget();
} else {
console.log();Not currently connected to ${networkSsid}
await Wifi.disconnect();
}
} else {
console.log();
}
} catch (error) {
console.error('Disconnect operation failed:', error);
}
};
// Usage examples
smartDisconnect('TempSetupNetwork', true); // Remove setup network
smartDisconnect('HomeWiFi', false); // Disconnect but keep saved
`
WiFi Connection Event Monitoring
Monitor WiFi connection state changes in real-time to detect when the device connects, disconnects, or switches between networks.
`typescript
import { Wifi } from '@tolutronics/capacitor-wifi';
import { PluginListenerHandle } from '@capacitor/core';
let wifiListener: PluginListenerHandle;
const startWifiMonitoring = async () => {
try {
// Set up event listener for WiFi connection changes
wifiListener = await Wifi.addListener('wifiConnectionChange', (event) => {
console.log('WiFi connection state changed:', {
isConnected: event.isConnected,
timestamp: new Date(event.timestamp).toLocaleString(),
wifi: event.wifi
});
if (event.isConnected && event.wifi) {
console.log(Connected to: ${event.wifi.ssid} (${event.wifi.bssid}));Signal strength: ${event.wifi.level} dBm
console.log();
} else {
console.log('Disconnected from WiFi network');
}
// Handle the event in your app logic
handleWifiStateChange(event);
});
console.log('WiFi monitoring started');
} catch (error) {
console.error('Failed to start WiFi monitoring:', error);
}
};
const stopWifiMonitoring = async () => {
if (wifiListener) {
await wifiListener.remove();
console.log('WiFi monitoring stopped');
}
};
// Handle WiFi state changes in your app
const handleWifiStateChange = (event) => {
if (event.isConnected) {
// Device connected to WiFi
onWifiConnected(event.wifi);
} else {
// Device disconnected from WiFi
onWifiDisconnected();
}
};
const onWifiConnected = (wifiInfo) => {
// Update UI, sync data, etc.
console.log('WiFi connected - enabling online features');
};
const onWifiDisconnected = () => {
// Handle offline state, show offline banner, etc.
console.log('WiFi disconnected - switching to offline mode');
};
// Start monitoring when app initializes
startWifiMonitoring();
// Remember to stop monitoring when the component/app is destroyed
// stopWifiMonitoring();
`
React Hook with Event Monitoring
`typescript
import { useState, useEffect } from 'react';
import { Wifi, WifiConnectionStateChangeEvent } from '@tolutronics/capacitor-wifi';
import { PluginListenerHandle } from '@capacitor/core';
interface WifiState {
isConnected: boolean;
currentWifi: any | null;
connectionHistory: WifiConnectionStateChangeEvent[];
}
export const useWifiMonitoring = () => {
const [wifiState, setWifiState] = useState
isConnected: false,
currentWifi: null,
connectionHistory: []
});
useEffect(() => {
let listener: PluginListenerHandle;
const setupWifiMonitoring = async () => {
try {
// Get initial state
const current = await Wifi.getCurrentWifi();
setWifiState(prev => ({
...prev,
isConnected: !!current.currentWifi,
currentWifi: current.currentWifi
}));
// Set up event listener
listener = await Wifi.addListener('wifiConnectionChange', (event) => {
setWifiState(prev => ({
isConnected: event.isConnected,
currentWifi: event.wifi || null,
connectionHistory: [event, ...prev.connectionHistory.slice(0, 9)] // Keep last 10 events
}));
});
} catch (error) {
console.error('Failed to setup WiFi monitoring:', error);
}
};
setupWifiMonitoring();
return () => {
if (listener) {
listener.remove();
}
};
}, []);
const refreshCurrentWifi = async () => {
try {
const result = await Wifi.getCurrentWifi();
setWifiState(prev => ({
...prev,
isConnected: !!result.currentWifi,
currentWifi: result.currentWifi
}));
} catch (error) {
console.error('Failed to refresh WiFi state:', error);
}
};
return {
...wifiState,
refreshCurrentWifi
};
};
// Usage in component
const WiFiStatusComponent = () => {
const { isConnected, currentWifi, connectionHistory } = useWifiMonitoring();
return (
Status: {isConnected ? 'Connected' : 'Disconnected'}
Network: {currentWifi.ssid}
Signal: {currentWifi.level} dBm
BSSID: {currentWifi.bssid}
: 'Disconnected'}
IoT Device Monitoring Example
$3
Monitor connection status when working with IoT devices to handle reconnection scenarios:
`typescript
const setupIoTDeviceWithMonitoring = async (devicePrefix: string, devicePassword: string) => {
let isSetupComplete = false; // Set up monitoring before connecting
const listener = await Wifi.addListener('wifiConnectionChange', (event) => {
if (!event.isConnected) {
console.log('Lost connection to device');
if (!isSetupComplete) {
console.log('Setup interrupted - may need to retry');
}
} else if (event.wifi?.ssid.startsWith(devicePrefix)) {
console.log(
Connected to device: ${event.wifi.ssid});
} else {
console.log(Connected to different network: ${event.wifi?.ssid});
}
}); try {
// Connect to device
await Wifi.connectToWifiBySsidPrefixAndPassword({
ssidPrefix: devicePrefix,
password: devicePassword
});
// Perform device configuration
await configureDevice();
isSetupComplete = true;
console.log('Device setup completed successfully');
} catch (error) {
console.error('Device setup failed:', error);
} finally {
// Clean up listener
await listener.remove();
}
};
const configureDevice = async () => {
// Your device configuration logic here
// This might include HTTP requests to the device's local IP
return new Promise(resolve => setTimeout(resolve, 5000)); // Simulated delay
};
`
Angular Component Example
$3
`typescript
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Wifi } from '@tolutronics/capacitor-wifi';
import { PluginListenerHandle } from '@capacitor/core';@Component({
selector: 'app-wifi-manager',
template:
{{ isConnected ? 'Connected' : 'Disconnected' }}
Network: {{ currentWifi.ssid }}
Signal: {{ currentWifi.level }} dBm
BSSID: {{ currentWifi.bssid }}
,
styles: []
})
export class WifiManagerComponent implements OnInit, OnDestroy {
isConnected = false;
currentWifi: any = null;
networks: any[] = [];
loading = false;
connectionHistory: any[] = []; private wifiListener?: PluginListenerHandle;
constructor() {}
async ngOnInit() {
await this.initializeWifiMonitoring();
await this.getCurrentWifiStatus();
}
ngOnDestroy() {
this.cleanup();
}
private async initializeWifiMonitoring() {
try {
// Check permissions first
const permissions = await Wifi.checkPermissions();
if (permissions.LOCATION !== 'granted' || permissions.NETWORK !== 'granted') {
const result = await Wifi.requestPermissions();
if (result.LOCATION !== 'granted' || result.NETWORK !== 'granted') {
console.error('WiFi permissions not granted');
return;
}
}
// Set up WiFi connection monitoring
this.wifiListener = await Wifi.addListener('wifiConnectionChange', (event) => {
console.log('WiFi connection changed:', event);
// Update component state
this.isConnected = event.isConnected;
this.currentWifi = event.wifi || null;
// Add to connection history
this.connectionHistory.unshift({
timestamp: event.timestamp,
isConnected: event.isConnected,
wifi: event.wifi
});
// Keep only last 10 entries
if (this.connectionHistory.length > 10) {
this.connectionHistory = this.connectionHistory.slice(0, 10);
}
// Handle the connection change
this.handleWifiConnectionChange(event);
});
console.log('WiFi monitoring initialized successfully');
} catch (error) {
console.error('Failed to initialize WiFi monitoring:', error);
}
}
private async getCurrentWifiStatus() {
try {
const result = await Wifi.getCurrentWifi();
this.isConnected = !!result.currentWifi;
this.currentWifi = result.currentWifi;
} catch (error) {
console.error('Failed to get current WiFi status:', error);
}
}
async scanNetworks() {
this.loading = true;
try {
const result = await Wifi.scanWifi();
this.networks = result.wifis;
console.log('Found networks:', this.networks.length);
} catch (error) {
console.error('Failed to scan networks:', error);
} finally {
this.loading = false;
}
}
async connectToNetwork(ssid: string) {
// In a real app, you'd get the password from user input
const password = prompt(
Enter password for ${ssid}:);
if (!password) return; this.loading = true;
try {
const result = await Wifi.connectToWifiBySsidAndPassword({
ssid,
password
});
if (result.wasSuccess) {
console.log('Connected successfully to:', ssid);
// Update current WiFi info
await this.getCurrentWifiStatus();
}
} catch (error) {
console.error('Failed to connect to network:', error);
} finally {
this.loading = false;
}
}
private handleWifiConnectionChange(event: any) {
if (event.isConnected && event.wifi) {
console.log(
Connected to WiFi: ${event.wifi.ssid});
// Handle WiFi connected state
// e.g., enable certain features, sync data, etc.
} else {
console.log('WiFi disconnected');
// Handle WiFi disconnected state
// e.g., show offline mode, disable certain features
}
} formatTimestamp(timestamp: number): string {
return new Date(timestamp).toLocaleTimeString();
}
private async cleanup() {
if (this.wifiListener) {
try {
await this.wifiListener.remove();
console.log('WiFi listener removed successfully');
} catch (error) {
console.error('Error removing WiFi listener:', error);
}
}
}
}
`
Angular Service Example
$3
For better separation of concerns, create a dedicated WiFi service:
`typescript
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Wifi } from '@tolutronics/capacitor-wifi';
import { PluginListenerHandle } from '@capacitor/core';export interface WifiState {
isConnected: boolean;
currentWifi: any | null;
networks: any[];
loading: boolean;
connectionHistory: any[];
}
@Injectable({
providedIn: 'root'
})
export class WifiService {
private wifiStateSubject = new BehaviorSubject({
isConnected: false,
currentWifi: null,
networks: [],
loading: false,
connectionHistory: []
});
private wifiListener?: PluginListenerHandle;
private isInitialized = false;
constructor() {
this.initialize();
}
get wifiState$(): Observable {
return this.wifiStateSubject.asObservable();
}
get currentState(): WifiState {
return this.wifiStateSubject.value;
}
private async initialize() {
if (this.isInitialized) return;
try {
// Check and request permissions
const permissions = await Wifi.checkPermissions();
if (permissions.LOCATION !== 'granted' || permissions.NETWORK !== 'granted') {
await Wifi.requestPermissions();
}
// Get initial WiFi state
await this.refreshCurrentWifi();
// Set up event listener
this.wifiListener = await Wifi.addListener('wifiConnectionChange', (event) => {
this.handleWifiConnectionChange(event);
});
this.isInitialized = true;
console.log('WiFi service initialized');
} catch (error) {
console.error('WiFi service initialization failed:', error);
}
}
private handleWifiConnectionChange(event: any) {
const currentState = this.currentState;
// Update connection history
const newHistory = [event, ...currentState.connectionHistory.slice(0, 9)];
// Update state
this.wifiStateSubject.next({
...currentState,
isConnected: event.isConnected,
currentWifi: event.wifi || null,
connectionHistory: newHistory
});
console.log('WiFi state updated:', {
isConnected: event.isConnected,
ssid: event.wifi?.ssid
});
}
async refreshCurrentWifi(): Promise {
try {
const result = await Wifi.getCurrentWifi();
const currentState = this.currentState;
this.wifiStateSubject.next({
...currentState,
isConnected: !!result.currentWifi,
currentWifi: result.currentWifi
});
} catch (error) {
console.error('Failed to refresh current WiFi:', error);
}
}
async scanNetworks(): Promise {
const currentState = this.currentState;
// Set loading state
this.wifiStateSubject.next({
...currentState,
loading: true
});
try {
const result = await Wifi.scanWifi();
this.wifiStateSubject.next({
...this.currentState,
networks: result.wifis,
loading: false
});
} catch (error) {
console.error('Failed to scan networks:', error);
this.wifiStateSubject.next({
...this.currentState,
loading: false
});
}
}
async connectToNetwork(ssid: string, password: string): Promise {
const currentState = this.currentState;
// Set loading state
this.wifiStateSubject.next({
...currentState,
loading: true
});
try {
const result = await Wifi.connectToWifiBySsidAndPassword({
ssid,
password
});
if (result.wasSuccess) {
await this.refreshCurrentWifi();
return true;
}
return false;
} catch (error) {
console.error('Failed to connect to network:', error);
return false;
} finally {
this.wifiStateSubject.next({
...this.currentState,
loading: false
});
}
}
async connectToIoTDevice(devicePrefix: string, password: string): Promise {
const currentState = this.currentState;
this.wifiStateSubject.next({
...currentState,
loading: true
});
try {
const result = await Wifi.connectToWifiBySsidPrefixAndPassword({
ssidPrefix: devicePrefix,
password
});
if (result.wasSuccess) {
await this.refreshCurrentWifi();
return true;
}
return false;
} catch (error) {
console.error('Failed to connect to IoT device:', error);
return false;
} finally {
this.wifiStateSubject.next({
...this.currentState,
loading: false
});
}
}
async disconnect(shouldForget: boolean = false): Promise {
try {
if (shouldForget) {
await Wifi.disconnectAndForget();
} else {
await Wifi.disconnect();
}
await this.refreshCurrentWifi();
} catch (error) {
console.error('Failed to disconnect:', error);
}
}
destroy(): void {
if (this.wifiListener) {
this.wifiListener.remove();
}
}
}
`
Usage in Your HomePage
$3
Now you can simplify your HomePage component:
`typescript
import { Component, OnDestroy, OnInit } from '@angular/core';
import { WifiService, WifiState } from './wifi.service';
import { Observable } from 'rxjs';@Component({
selector: 'app-home',
template:
{{ wifiState.isConnected ? 'Connected' : 'Disconnected' }}
{{ wifiState.currentWifi.ssid }}
Signal: {{ wifiState.currentWifi.level }} dBm
})
export class HomePage implements OnInit, OnDestroy {
public isTracking = false;
public wifiState$: Observable; constructor(private wifiService: WifiService) {
this.wifiState$ = this.wifiService.wifiState$;
}
ngOnInit() {
// WiFi monitoring is automatically initialized by the service
}
ngOnDestroy() {
// Service cleanup is handled globally, but you can call it here if needed
// this.wifiService.destroy();
}
async scanNetworks() {
await this.wifiService.scanNetworks();
}
toggleTracking() {
this.isTracking = !this.isTracking;
// Your tracking logic here
}
}
`
React/Vue Component Example
$3
`typescript
// React Hook Example
import { useState, useEffect } from 'react';
import { Wifi } from '@tolutronics/capacitor-wifi';export const useWifi = () => {
const [networks, setNetworks] = useState([]);
const [currentWifi, setCurrentWifi] = useState(null);
const [loading, setLoading] = useState(false);
const scanNetworks = async () => {
setLoading(true);
try {
const result = await Wifi.scanWifi();
setNetworks(result.wifis);
} catch (error) {
console.error('Scan failed:', error);
} finally {
setLoading(false);
}
};
const connectToNetwork = async (ssid: string, password: string) => {
setLoading(true);
try {
await Wifi.connectToWifiBySsidAndPassword({ ssid, password });
// Refresh current WiFi info
const current = await Wifi.getCurrentWifi();
setCurrentWifi(current.currentWifi);
} catch (error) {
console.error('Connection failed:', error);
} finally {
setLoading(false);
}
};
return {
networks,
currentWifi,
loading,
scanNetworks,
connectToNetwork
};
};
`API
scanWifi()
* getCurrentWifi()
* connectToWifiBySsidAndPassword(...)
* connectToWifiBySsidPrefixAndPassword(...)
* checkPermissions()
* requestPermissions()
* disconnectAndForget()
* disconnect()
* addListener('wifiConnectionChange', ...)
* removeAllListeners()
* Interfaces
* Type Aliases
* Enums
$3
`typescript
scanWifi() => Promise
`Returns: Promise<ScanWifiResult>
--------------------
$3
`typescript
getCurrentWifi() => Promise
`Returns: Promise<GetCurrentWifiResult>
--------------------
$3
`typescript
connectToWifiBySsidAndPassword(connectToWifiRequest: ConnectToWifiRequest) => Promise
`| Param | Type |
| -------------------------- | --------------------------------------------------------------------- |
|
connectToWifiRequest | ConnectToWifiRequest |Returns: Promise<ConnectToWifiResult>
--------------------
$3
`typescript
connectToWifiBySsidPrefixAndPassword(connectToWifiPrefixRequest: ConnectToWifiPrefixRequest) => Promise
`| Param | Type |
| -------------------------------- | --------------------------------------------------------------------------------- |
|
connectToWifiPrefixRequest | ConnectToWifiPrefixRequest |Returns: Promise<ConnectToWifiResult>
--------------------
$3
`typescript
checkPermissions() => Promise
`Returns: Promise<PermissionStatus>
--------------------
$3
`typescript
requestPermissions() => Promise
`Returns: Promise<PermissionStatus>
--------------------
$3
`typescript
disconnectAndForget() => Promise
`--------------------
$3
`typescript
disconnect() => Promise
`Disconnect from the current WiFi network without removing it from saved networks.
The network configuration remains saved and the device can auto-reconnect later.
--------------------
$3
`typescript
addListener(eventName: 'wifiConnectionChange', listenerFunc: WifiConnectionListener) => Promise & PluginListenerHandle
`Listen for WiFi connection state changes
| Param | Type | Description |
| ------------------ | ------------------------------------------------------------------------- | ------------------------------------------ |
|
eventName | 'wifiConnectionChange' | The event name to listen for |
| listenerFunc | WifiConnectionListener | The function to call when the event occurs |Returns: Promise<PluginListenerHandle> & PluginListenerHandle
--------------------
$3
`typescript
removeAllListeners() => Promise
`Remove all listeners for this plugin
--------------------
$3
#### ScanWifiResult
| Prop | Type |
| ----------- | ------------------------ |
|
wifis | WifiEntry[] |
#### WifiEntry
| Prop | Type |
| ------------------- | ----------------------------- |
|
bssid | string |
| capabilities | WifiCapability[] |
| ssid | string |
| level | number |
| isCurrentWifi | boolean |
#### GetCurrentWifiResult
| Prop | Type |
| ----------------- | ----------------------------------------------- |
|
currentWifi | WifiEntry |
#### ConnectToWifiResult
| Prop | Type |
| ---------------- | ----------------------------------------------- |
|
wasSuccess | true |
| wifi | WifiEntry |
#### ConnectToWifiRequest
| Prop | Type |
| -------------- | ------------------- |
|
ssid | string |
| password | string |
#### ConnectToWifiPrefixRequest
| Prop | Type |
| ---------------- | ------------------- |
|
ssidPrefix | string |
| password | string |
#### PermissionStatus
| Prop | Type |
| -------------- | ----------------------------------------------------------- |
|
LOCATION | PermissionState |
| NETWORK | PermissionState |
#### PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
|
remove | () => Promise<void> |
#### WifiConnectionListener
$3
#### PermissionState
'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'
$3
#### WifiCapability
| Members | Value |
| ----------------------- | -------------------------------- |
|
WPA2_PSK_CCM | 'WPA2-PSK-CCM' |
| RSN_PSK_CCMP | 'RSN-PSK-CCMP' |
| RSN_SAE_CCM | 'RSN-SAE-CCM' |
| WPA2_EAP_SHA1_CCM | 'WPA2-EAP/SHA1-CCM' |
| RSN_EAP_SHA1_CCMP | 'RSN-EAP/SHA1-CCMP' |
| ESS | 'ESS' |
| ES | 'ES' |
| WP | 'WP' |
#### SpecialSsid
| Members | Value |
| ------------ | ---------------------------- |
|
HIDDEN | '[HIDDEN_SSID]' |🔧 Troubleshooting & Tips
$3
❌ "METHOD_UNIMPLEMENTED" Error
- This occurs when running in a web browser. The plugin only works on native iOS/Android platforms.
- Solution: Test on device/emulator using
npx cap run ios or npx cap run android❌ Permission Denied Errors
- Location permissions are required for WiFi scanning on both platforms.
- Solution: Always call
checkPermissions() and requestPermissions() before other operations.❌ Connection Failures
- Some devices may have restrictions on programmatic WiFi connections.
- Solution: Test on multiple devices and handle errors gracefully.
$3
📱 iOS
- Uses
NetworkExtension framework for connections
- joinOnce is set to true for temporary connections
- Location permission required for WiFi scanning
- Works on iOS 13.0+iOS Setup Required:
1. Add Required Capabilities in Xcode:
- Open your app's
.xcworkspace file in Xcode
- Select your App target (not Capacitor or plugin targets)
- Go to "Signing & Capabilities" tab
- Click "+ Capability" and add:
- "Access WiFi Information" - Required for getting current WiFi info
- "Hotspot Configuration" - Required for connecting to WiFi networks2. Add Location Permission to Info.plist:
`xml
NSLocationWhenInUseUsageDescription
This app needs location access to scan for WiFi networks NSLocationAlwaysAndWhenInUseUsageDescription
This app needs location access to scan for WiFi networks
`3. Verify Entitlements File:
- Xcode automatically creates
App.entitlements when you add capabilities
- Should contain:
`xml
com.apple.developer.networking.HotspotConfiguration
com.apple.developer.networking.wifi-info
`Important iOS Notes:
- Must test on real device - iOS Simulator doesn't support WiFi operations
- App must be in foreground for WiFi operations to work
- WiFi scanning only returns currently connected network (iOS security limitation)
- Location permission must be granted before any WiFi operations
🤖 Android
- Uses
WifiManager and ConnectivityManager for operations
- Requires multiple network permissions (see installation notes)
- Network callback monitoring for real-time events
- Works on Android API 26+$3
- Event Listeners: Remember to remove listeners when components unmount to prevent memory leaks
- Background Monitoring: WiFi monitoring automatically starts/stops with plugin lifecycle
- Batch Operations: Wait for connection completion before performing additional network operations
- Error Handling: Always wrap WiFi operations in try-catch blocks
$3
- Use
connectToWifiBySsidPrefixAndPassword()` for devices with dynamic SSIDs1. Test Permissions First: Always verify permissions work correctly
2. Use Real Devices: WiFi operations don't work in simulators/emulators reliably
3. Monitor Events: Use event listeners during development to understand timing
4. Handle Edge Cases: Network switching, airplane mode, etc.
---
While this plugin was developed from scratch, we acknowledge the inspiration and lessons learned from the broader Capacitor community, including:
- @capacitor-community/wifi - Community WiFi plugin that demonstrated basic WiFi operations
- Capacitor Core Team - For creating an excellent framework that makes native plugin development accessible
- The broader Capacitor plugin community - For sharing best practices and patterns for plugin development
This plugin builds upon the collective knowledge of the community while addressing specific gaps in functionality, particularly for IoT device workflows and real-time network monitoring.
MIT
Contributions are welcome! Please feel free to submit a Pull Request.
If you encounter any issues or have questions, please create an issue on GitHub.
---
Built with ❤️ for the Capacitor community