@capgo/capacitor-wifi 8.0.5 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/android/src/main/java/ee/forgr/plugin/capacitor_wifi/CapacitorWifiPlugin.java +79 -5
- package/dist/docs.json +18 -2
- package/dist/esm/definitions.d.ts +12 -1
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/CapacitorWifiPlugin/CapacitorWifiPlugin.swift +1 -1
- package/package.json +1 -1
- package/android/src/main/java/app/capgo/capacitorwifi/CapacitorWifiPlugin.java +0 -439
package/README.md
CHANGED
|
@@ -92,6 +92,7 @@ connect(options: ConnectOptions) => Promise<void>
|
|
|
92
92
|
|
|
93
93
|
Connect to a Wi-Fi network.
|
|
94
94
|
On Android, this creates a temporary connection that doesn't route traffic through the network by default.
|
|
95
|
+
Set autoRouteTraffic to true to bind app traffic to the connected network (useful for local/device-hosted APs).
|
|
95
96
|
For a persistent connection on Android, use addNetwork() instead.
|
|
96
97
|
On iOS, this creates a persistent connection.
|
|
97
98
|
|
|
@@ -323,11 +324,12 @@ Options for adding a network
|
|
|
323
324
|
|
|
324
325
|
Options for connecting to a network
|
|
325
326
|
|
|
326
|
-
| Prop
|
|
327
|
-
|
|
|
328
|
-
| **`ssid`**
|
|
329
|
-
| **`password`**
|
|
330
|
-
| **`isHiddenSsid`**
|
|
327
|
+
| Prop | Type | Description | Default | Since |
|
|
328
|
+
| ---------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
|
|
329
|
+
| **`ssid`** | <code>string</code> | The SSID of the network to connect to | | 7.0.0 |
|
|
330
|
+
| **`password`** | <code>string</code> | The password for the network (optional for open networks) | | 7.0.0 |
|
|
331
|
+
| **`isHiddenSsid`** | <code>boolean</code> | Whether the network is hidden (Android only) | <code>false</code> | 7.0.0 |
|
|
332
|
+
| **`autoRouteTraffic`** | <code>boolean</code> | Whether to automatically route app traffic through the connected Wi-Fi network (Android only) When enabled, it binds the app process to the connected network using ConnectivityManager.bindProcessToNetwork() This is useful for connecting to local/device-hosted APs (e.g., ESP32, IoT devices) that don't have internet access. | <code>false</code> | 7.0.0 |
|
|
331
333
|
|
|
332
334
|
|
|
333
335
|
#### DisconnectOptions
|
|
@@ -44,12 +44,14 @@ import java.util.List;
|
|
|
44
44
|
)
|
|
45
45
|
public class CapacitorWifiPlugin extends Plugin {
|
|
46
46
|
|
|
47
|
-
private final String pluginVersion = "8.0
|
|
47
|
+
private final String pluginVersion = "8.1.0";
|
|
48
48
|
|
|
49
49
|
private WifiManager wifiManager;
|
|
50
50
|
private ConnectivityManager connectivityManager;
|
|
51
51
|
private BroadcastReceiver scanResultsReceiver;
|
|
52
52
|
private ConnectivityManager.NetworkCallback networkCallback;
|
|
53
|
+
private Network boundNetwork; // Store the network we bound to for unbinding
|
|
54
|
+
private final Object boundNetworkLock = new Object(); // Lock for thread-safe access to boundNetwork
|
|
53
55
|
|
|
54
56
|
@Override
|
|
55
57
|
public void load() {
|
|
@@ -201,6 +203,7 @@ public class CapacitorWifiPlugin extends Plugin {
|
|
|
201
203
|
|
|
202
204
|
String password = call.getString("password");
|
|
203
205
|
Boolean isHiddenSsid = call.getBoolean("isHiddenSsid", false);
|
|
206
|
+
Boolean autoRouteTraffic = call.getBoolean("autoRouteTraffic", false);
|
|
204
207
|
|
|
205
208
|
try {
|
|
206
209
|
WifiNetworkSpecifier.Builder specifierBuilder = new WifiNetworkSpecifier.Builder().setSsid(ssid);
|
|
@@ -215,16 +218,46 @@ public class CapacitorWifiPlugin extends Plugin {
|
|
|
215
218
|
|
|
216
219
|
NetworkSpecifier specifier = specifierBuilder.build();
|
|
217
220
|
|
|
218
|
-
NetworkRequest
|
|
221
|
+
NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder()
|
|
219
222
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
|
220
|
-
.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
.setNetworkSpecifier(specifier);
|
|
224
|
+
|
|
225
|
+
// Only remove internet capability if autoRouteTraffic is false
|
|
226
|
+
// If autoRouteTraffic is true, we want Android to consider this network valid for routing
|
|
227
|
+
if (autoRouteTraffic == null || !autoRouteTraffic) {
|
|
228
|
+
requestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
NetworkRequest request = requestBuilder.build();
|
|
223
232
|
|
|
224
233
|
networkCallback = new ConnectivityManager.NetworkCallback() {
|
|
225
234
|
@Override
|
|
226
235
|
public void onAvailable(@NonNull Network network) {
|
|
227
236
|
super.onAvailable(network);
|
|
237
|
+
|
|
238
|
+
// Bind process to network if autoRouteTraffic is enabled
|
|
239
|
+
if (autoRouteTraffic != null && autoRouteTraffic) {
|
|
240
|
+
try {
|
|
241
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
242
|
+
synchronized (boundNetworkLock) {
|
|
243
|
+
// Unbind from previous network if any
|
|
244
|
+
if (boundNetwork != null) {
|
|
245
|
+
connectivityManager.bindProcessToNetwork(null);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Bind to the new network
|
|
249
|
+
boolean bound = connectivityManager.bindProcessToNetwork(network);
|
|
250
|
+
if (bound) {
|
|
251
|
+
boundNetwork = network;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
} catch (Exception e) {
|
|
256
|
+
// Log error but don't fail the connection
|
|
257
|
+
android.util.Log.e("CapacitorWifi", "Failed to bind process to network: " + e.getMessage());
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
228
261
|
call.resolve();
|
|
229
262
|
}
|
|
230
263
|
|
|
@@ -255,6 +288,7 @@ public class CapacitorWifiPlugin extends Plugin {
|
|
|
255
288
|
|
|
256
289
|
String password = call.getString("password");
|
|
257
290
|
Boolean isHiddenSsid = call.getBoolean("isHiddenSsid", false);
|
|
291
|
+
Boolean autoRouteTraffic = call.getBoolean("autoRouteTraffic", false);
|
|
258
292
|
|
|
259
293
|
try {
|
|
260
294
|
WifiConfiguration wifiConfig = new WifiConfiguration();
|
|
@@ -294,6 +328,37 @@ public class CapacitorWifiPlugin extends Plugin {
|
|
|
294
328
|
return;
|
|
295
329
|
}
|
|
296
330
|
|
|
331
|
+
// Bind process to network if autoRouteTraffic is enabled
|
|
332
|
+
if (autoRouteTraffic != null && autoRouteTraffic) {
|
|
333
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
334
|
+
// Use handler to bind asynchronously after connection is established
|
|
335
|
+
new android.os.Handler(android.os.Looper.getMainLooper()).postDelayed(
|
|
336
|
+
() -> {
|
|
337
|
+
try {
|
|
338
|
+
synchronized (boundNetworkLock) {
|
|
339
|
+
// Unbind from previous network if any
|
|
340
|
+
if (boundNetwork != null) {
|
|
341
|
+
connectivityManager.bindProcessToNetwork(null);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
Network activeNetwork = connectivityManager.getActiveNetwork();
|
|
345
|
+
if (activeNetwork != null) {
|
|
346
|
+
boolean bound = connectivityManager.bindProcessToNetwork(activeNetwork);
|
|
347
|
+
if (bound) {
|
|
348
|
+
boundNetwork = activeNetwork;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
} catch (Exception e) {
|
|
353
|
+
// Log error but don't fail the connection
|
|
354
|
+
android.util.Log.e("CapacitorWifi", "Failed to bind process to network: " + e.getMessage());
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
500
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
297
362
|
call.resolve();
|
|
298
363
|
} catch (Exception e) {
|
|
299
364
|
call.reject("Failed to connect: " + e.getMessage(), e);
|
|
@@ -303,6 +368,15 @@ public class CapacitorWifiPlugin extends Plugin {
|
|
|
303
368
|
@PluginMethod
|
|
304
369
|
public void disconnect(PluginCall call) {
|
|
305
370
|
try {
|
|
371
|
+
// Unbind from network if we were bound
|
|
372
|
+
synchronized (boundNetworkLock) {
|
|
373
|
+
if (boundNetwork != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
374
|
+
connectivityManager.bindProcessToNetwork(null);
|
|
375
|
+
boundNetwork = null;
|
|
376
|
+
android.util.Log.d("CapacitorWifi", "Unbound process from network");
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
306
380
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
307
381
|
if (networkCallback != null) {
|
|
308
382
|
connectivityManager.unregisterNetworkCallback(networkCallback);
|
package/dist/docs.json
CHANGED
|
@@ -79,10 +79,10 @@
|
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
"name": "example",
|
|
82
|
-
"text": "```typescript\nawait CapacitorWifi.connect({\n ssid: 'MyNetwork',\n password: 'mypassword'\n});\n```"
|
|
82
|
+
"text": "```typescript\nawait CapacitorWifi.connect({\n ssid: 'MyNetwork',\n password: 'mypassword',\n autoRouteTraffic: true // Android only: route app traffic through this network\n});\n```"
|
|
83
83
|
}
|
|
84
84
|
],
|
|
85
|
-
"docs": "Connect to a Wi-Fi network.\nOn Android, this creates a temporary connection that doesn't route traffic through the network by default.\nFor a persistent connection on Android, use addNetwork() instead.\nOn iOS, this creates a persistent connection.",
|
|
85
|
+
"docs": "Connect to a Wi-Fi network.\nOn Android, this creates a temporary connection that doesn't route traffic through the network by default.\nSet autoRouteTraffic to true to bind app traffic to the connected network (useful for local/device-hosted APs).\nFor a persistent connection on Android, use addNetwork() instead.\nOn iOS, this creates a persistent connection.",
|
|
86
86
|
"complexTypes": [
|
|
87
87
|
"ConnectOptions"
|
|
88
88
|
],
|
|
@@ -589,6 +589,22 @@
|
|
|
589
589
|
"docs": "Whether the network is hidden (Android only)",
|
|
590
590
|
"complexTypes": [],
|
|
591
591
|
"type": "boolean | undefined"
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
"name": "autoRouteTraffic",
|
|
595
|
+
"tags": [
|
|
596
|
+
{
|
|
597
|
+
"text": "7.0.0",
|
|
598
|
+
"name": "since"
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
"text": "false",
|
|
602
|
+
"name": "default"
|
|
603
|
+
}
|
|
604
|
+
],
|
|
605
|
+
"docs": "Whether to automatically route app traffic through the connected Wi-Fi network (Android only)\nWhen enabled, it binds the app process to the connected network using ConnectivityManager.bindProcessToNetwork()\nThis is useful for connecting to local/device-hosted APs (e.g., ESP32, IoT devices) that don't have internet access.",
|
|
606
|
+
"complexTypes": [],
|
|
607
|
+
"type": "boolean | undefined"
|
|
592
608
|
}
|
|
593
609
|
]
|
|
594
610
|
},
|
|
@@ -28,6 +28,7 @@ export interface CapacitorWifiPlugin {
|
|
|
28
28
|
/**
|
|
29
29
|
* Connect to a Wi-Fi network.
|
|
30
30
|
* On Android, this creates a temporary connection that doesn't route traffic through the network by default.
|
|
31
|
+
* Set autoRouteTraffic to true to bind app traffic to the connected network (useful for local/device-hosted APs).
|
|
31
32
|
* For a persistent connection on Android, use addNetwork() instead.
|
|
32
33
|
* On iOS, this creates a persistent connection.
|
|
33
34
|
*
|
|
@@ -39,7 +40,8 @@ export interface CapacitorWifiPlugin {
|
|
|
39
40
|
* ```typescript
|
|
40
41
|
* await CapacitorWifi.connect({
|
|
41
42
|
* ssid: 'MyNetwork',
|
|
42
|
-
* password: 'mypassword'
|
|
43
|
+
* password: 'mypassword',
|
|
44
|
+
* autoRouteTraffic: true // Android only: route app traffic through this network
|
|
43
45
|
* });
|
|
44
46
|
* ```
|
|
45
47
|
*/
|
|
@@ -282,6 +284,15 @@ export interface ConnectOptions {
|
|
|
282
284
|
* @default false
|
|
283
285
|
*/
|
|
284
286
|
isHiddenSsid?: boolean;
|
|
287
|
+
/**
|
|
288
|
+
* Whether to automatically route app traffic through the connected Wi-Fi network (Android only)
|
|
289
|
+
* When enabled, it binds the app process to the connected network using ConnectivityManager.bindProcessToNetwork()
|
|
290
|
+
* This is useful for connecting to local/device-hosted APs (e.g., ESP32, IoT devices) that don't have internet access.
|
|
291
|
+
*
|
|
292
|
+
* @since 7.0.0
|
|
293
|
+
* @default false
|
|
294
|
+
*/
|
|
295
|
+
autoRouteTraffic?: boolean;
|
|
285
296
|
}
|
|
286
297
|
/**
|
|
287
298
|
* Options for disconnecting from a network
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAocA;;;;GAIG;AACH,MAAM,CAAN,IAAY,mBA6EX;AA7ED,WAAY,mBAAmB;IAC7B;;;;OAIG;IACH,6DAAQ,CAAA;IAER;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,qEAAY,CAAA;IAEZ;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,mFAAmB,CAAA;IAEnB;;;;OAIG;IACH,mGAA2B,CAAA;IAE3B;;;;OAIG;IACH,uEAAa,CAAA;IAEb;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,qEAAY,CAAA;IAEZ;;;;OAIG;IACH,wEAAc,CAAA;AAChB,CAAC,EA7EW,mBAAmB,KAAnB,mBAAmB,QA6E9B","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n/**\n * WiFi plugin for managing device WiFi connectivity\n *\n * @since 7.0.0\n */\nexport interface CapacitorWifiPlugin {\n /**\n * Show a system dialog to add a Wi-Fi network to the device.\n * On Android SDK 30+, this opens the system Wi-Fi settings with the network pre-filled.\n * On iOS, this connects to the network directly.\n *\n * @param options - Network configuration options\n * @returns Promise that resolves when the network is added\n * @throws Error if adding the network fails\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.addNetwork({\n * ssid: 'MyNetwork',\n * password: 'mypassword',\n * isHiddenSsid: false,\n * securityType: NetworkSecurityType.WPA2_PSK\n * });\n * ```\n */\n addNetwork(options: AddNetworkOptions): Promise<void>;\n\n /**\n * Connect to a Wi-Fi network.\n * On Android, this creates a temporary connection that doesn't route traffic through the network by default.\n * For a persistent connection on Android, use addNetwork() instead.\n * On iOS, this creates a persistent connection.\n *\n * @param options - Connection options\n * @returns Promise that resolves when connected\n * @throws Error if connection fails\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.connect({\n * ssid: 'MyNetwork',\n * password: 'mypassword'\n * });\n * ```\n */\n connect(options: ConnectOptions): Promise<void>;\n\n /**\n * Disconnect from the current Wi-Fi network.\n * On iOS, only disconnects from networks that were added via this plugin.\n *\n * @param options - Optional disconnect options\n * @returns Promise that resolves when disconnected\n * @throws Error if disconnection fails\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.disconnect();\n * ```\n */\n disconnect(options?: DisconnectOptions): Promise<void>;\n\n /**\n * Get a list of available Wi-Fi networks from the last scan.\n * Only available on Android.\n *\n * @returns Promise that resolves with the list of networks\n * @throws Error if getting networks fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * const { networks } = await CapacitorWifi.getAvailableNetworks();\n * networks.forEach(network => {\n * console.log(`SSID: ${network.ssid}, Signal: ${network.rssi} dBm`);\n * });\n * ```\n */\n getAvailableNetworks(): Promise<GetAvailableNetworksResult>;\n\n /**\n * Get the device's current IP address.\n * Available on both Android and iOS.\n *\n * @returns Promise that resolves with the IP address\n * @throws Error if getting IP address fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const { ipAddress } = await CapacitorWifi.getIpAddress();\n * console.log('IP Address:', ipAddress);\n * ```\n */\n getIpAddress(): Promise<GetIpAddressResult>;\n\n /**\n * Get the received signal strength indicator (RSSI) of the current network in dBm.\n * Only available on Android.\n *\n * @returns Promise that resolves with the RSSI value\n * @throws Error if getting RSSI fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * const { rssi } = await CapacitorWifi.getRssi();\n * console.log('Signal strength:', rssi, 'dBm');\n * ```\n */\n getRssi(): Promise<GetRssiResult>;\n\n /**\n * Get the service set identifier (SSID) of the current network.\n * Available on both Android and iOS.\n *\n * @returns Promise that resolves with the SSID\n * @throws Error if getting SSID fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const { ssid } = await CapacitorWifi.getSsid();\n * console.log('Connected to:', ssid);\n * ```\n */\n getSsid(): Promise<GetSsidResult>;\n\n /**\n * Check if Wi-Fi is enabled on the device.\n * Only available on Android.\n *\n * @returns Promise that resolves with the Wi-Fi enabled status\n * @throws Error if checking status fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * const { enabled } = await CapacitorWifi.isEnabled();\n * console.log('WiFi is', enabled ? 'enabled' : 'disabled');\n * ```\n */\n isEnabled(): Promise<IsEnabledResult>;\n\n /**\n * Start scanning for Wi-Fi networks.\n * Only available on Android.\n * Results are delivered via the 'networksScanned' event listener.\n * Note: May fail due to system throttling or hardware issues.\n *\n * @returns Promise that resolves when scan starts\n * @throws Error if scan fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.addListener('networksScanned', () => {\n * console.log('Scan completed');\n * });\n * await CapacitorWifi.startScan();\n * ```\n */\n startScan(): Promise<void>;\n\n /**\n * Check the current permission status for location access.\n * Location permission is required for Wi-Fi operations on both platforms.\n *\n * @returns Promise that resolves with the permission status\n * @throws Error if checking permissions fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const status = await CapacitorWifi.checkPermissions();\n * console.log('Location permission:', status.location);\n * ```\n */\n checkPermissions(): Promise<PermissionStatus>;\n\n /**\n * Request location permissions from the user.\n * Location permission is required for Wi-Fi operations on both platforms.\n *\n * @param options - Optional permission request options\n * @returns Promise that resolves with the updated permission status\n * @throws Error if requesting permissions fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const status = await CapacitorWifi.requestPermissions();\n * if (status.location === 'granted') {\n * console.log('Permission granted');\n * }\n * ```\n */\n requestPermissions(options?: RequestPermissionsOptions): Promise<PermissionStatus>;\n\n /**\n * Add a listener for the 'networksScanned' event.\n * Only available on Android.\n * This event is fired when Wi-Fi scan results are available.\n *\n * @param eventName - The event name ('networksScanned')\n * @param listenerFunc - The callback function to execute\n * @returns Promise that resolves with a listener handle\n * @since 7.0.0\n * @example\n * ```typescript\n * const listener = await CapacitorWifi.addListener('networksScanned', async () => {\n * const { networks } = await CapacitorWifi.getAvailableNetworks();\n * console.log('Found networks:', networks);\n * });\n * ```\n */\n addListener(eventName: 'networksScanned', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Remove all listeners for this plugin.\n *\n * @returns Promise that resolves when all listeners are removed\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.removeAllListeners();\n * ```\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Get the native plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const { version } = await CapacitorWifi.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n\n/**\n * Options for adding a network\n *\n * @since 7.0.0\n */\nexport interface AddNetworkOptions {\n /**\n * The SSID of the network to add\n *\n * @since 7.0.0\n */\n ssid: string;\n\n /**\n * The password for the network (optional for open networks)\n *\n * @since 7.0.0\n */\n password?: string;\n\n /**\n * Whether the network is hidden (Android only)\n *\n * @since 7.0.0\n * @default false\n */\n isHiddenSsid?: boolean;\n\n /**\n * The security type of the network (Android only)\n *\n * @since 7.0.0\n * @default NetworkSecurityType.WPA2_PSK\n */\n securityType?: NetworkSecurityType;\n}\n\n/**\n * Options for connecting to a network\n *\n * @since 7.0.0\n */\nexport interface ConnectOptions {\n /**\n * The SSID of the network to connect to\n *\n * @since 7.0.0\n */\n ssid: string;\n\n /**\n * The password for the network (optional for open networks)\n *\n * @since 7.0.0\n */\n password?: string;\n\n /**\n * Whether the network is hidden (Android only)\n *\n * @since 7.0.0\n * @default false\n */\n isHiddenSsid?: boolean;\n}\n\n/**\n * Options for disconnecting from a network\n *\n * @since 7.0.0\n */\nexport interface DisconnectOptions {\n /**\n * The SSID of the network to disconnect from (optional)\n *\n * @since 7.0.0\n */\n ssid?: string;\n}\n\n/**\n * Result from getAvailableNetworks()\n *\n * @since 7.0.0\n */\nexport interface GetAvailableNetworksResult {\n /**\n * List of available networks\n *\n * @since 7.0.0\n */\n networks: Network[];\n}\n\n/**\n * Represents a Wi-Fi network\n *\n * @since 7.0.0\n */\nexport interface Network {\n /**\n * The SSID of the network\n *\n * @since 7.0.0\n */\n ssid: string;\n\n /**\n * The signal strength in dBm\n *\n * @since 7.0.0\n */\n rssi: number;\n\n /**\n * The security types supported by this network (Android SDK 33+ only)\n *\n * @since 7.0.0\n */\n securityTypes?: NetworkSecurityType[];\n}\n\n/**\n * Result from getIpAddress()\n *\n * @since 7.0.0\n */\nexport interface GetIpAddressResult {\n /**\n * The device's IP address\n *\n * @since 7.0.0\n */\n ipAddress: string;\n}\n\n/**\n * Result from getRssi()\n *\n * @since 7.0.0\n */\nexport interface GetRssiResult {\n /**\n * The signal strength in dBm\n *\n * @since 7.0.0\n */\n rssi: number;\n}\n\n/**\n * Result from getSsid()\n *\n * @since 7.0.0\n */\nexport interface GetSsidResult {\n /**\n * The SSID of the current network\n *\n * @since 7.0.0\n */\n ssid: string;\n}\n\n/**\n * Result from isEnabled()\n *\n * @since 7.0.0\n */\nexport interface IsEnabledResult {\n /**\n * Whether Wi-Fi is enabled\n *\n * @since 7.0.0\n */\n enabled: boolean;\n}\n\n/**\n * Permission status\n *\n * @since 7.0.0\n */\nexport interface PermissionStatus {\n /**\n * Location permission state\n *\n * @since 7.0.0\n */\n location: PermissionState;\n}\n\n/**\n * Possible permission states\n *\n * @since 7.0.0\n */\nexport type PermissionState = 'granted' | 'denied' | 'prompt';\n\n/**\n * Options for requesting permissions\n *\n * @since 7.0.0\n */\nexport interface RequestPermissionsOptions {\n /**\n * Permissions to request\n *\n * @since 7.0.0\n */\n permissions?: 'location'[];\n}\n\n/**\n * Network security types\n *\n * @since 7.0.0\n */\nexport enum NetworkSecurityType {\n /**\n * Open network with no security\n *\n * @since 7.0.0\n */\n OPEN = 0,\n\n /**\n * WEP security\n *\n * @since 7.0.0\n */\n WEP = 1,\n\n /**\n * WPA/WPA2 Personal (PSK)\n *\n * @since 7.0.0\n */\n WPA2_PSK = 2,\n\n /**\n * WPA/WPA2/WPA3 Enterprise (EAP)\n *\n * @since 7.0.0\n */\n EAP = 3,\n\n /**\n * WPA3 Personal (SAE)\n *\n * @since 7.0.0\n */\n SAE = 4,\n\n /**\n * WPA3 Enterprise\n *\n * @since 7.0.0\n */\n WPA3_ENTERPRISE = 5,\n\n /**\n * WPA3 Enterprise 192-bit mode\n *\n * @since 7.0.0\n */\n WPA3_ENTERPRISE_192_BIT = 6,\n\n /**\n * Passpoint network\n *\n * @since 7.0.0\n */\n PASSPOINT = 7,\n\n /**\n * Enhanced Open (OWE)\n *\n * @since 7.0.0\n */\n OWE = 8,\n\n /**\n * WAPI PSK\n *\n * @since 7.0.0\n */\n WAPI_PSK = 9,\n\n /**\n * WAPI Certificate\n *\n * @since 7.0.0\n */\n WAPI_CERT = 10,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAgdA;;;;GAIG;AACH,MAAM,CAAN,IAAY,mBA6EX;AA7ED,WAAY,mBAAmB;IAC7B;;;;OAIG;IACH,6DAAQ,CAAA;IAER;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,qEAAY,CAAA;IAEZ;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,mFAAmB,CAAA;IAEnB;;;;OAIG;IACH,mGAA2B,CAAA;IAE3B;;;;OAIG;IACH,uEAAa,CAAA;IAEb;;;;OAIG;IACH,2DAAO,CAAA;IAEP;;;;OAIG;IACH,qEAAY,CAAA;IAEZ;;;;OAIG;IACH,wEAAc,CAAA;AAChB,CAAC,EA7EW,mBAAmB,KAAnB,mBAAmB,QA6E9B","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n/**\n * WiFi plugin for managing device WiFi connectivity\n *\n * @since 7.0.0\n */\nexport interface CapacitorWifiPlugin {\n /**\n * Show a system dialog to add a Wi-Fi network to the device.\n * On Android SDK 30+, this opens the system Wi-Fi settings with the network pre-filled.\n * On iOS, this connects to the network directly.\n *\n * @param options - Network configuration options\n * @returns Promise that resolves when the network is added\n * @throws Error if adding the network fails\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.addNetwork({\n * ssid: 'MyNetwork',\n * password: 'mypassword',\n * isHiddenSsid: false,\n * securityType: NetworkSecurityType.WPA2_PSK\n * });\n * ```\n */\n addNetwork(options: AddNetworkOptions): Promise<void>;\n\n /**\n * Connect to a Wi-Fi network.\n * On Android, this creates a temporary connection that doesn't route traffic through the network by default.\n * Set autoRouteTraffic to true to bind app traffic to the connected network (useful for local/device-hosted APs).\n * For a persistent connection on Android, use addNetwork() instead.\n * On iOS, this creates a persistent connection.\n *\n * @param options - Connection options\n * @returns Promise that resolves when connected\n * @throws Error if connection fails\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.connect({\n * ssid: 'MyNetwork',\n * password: 'mypassword',\n * autoRouteTraffic: true // Android only: route app traffic through this network\n * });\n * ```\n */\n connect(options: ConnectOptions): Promise<void>;\n\n /**\n * Disconnect from the current Wi-Fi network.\n * On iOS, only disconnects from networks that were added via this plugin.\n *\n * @param options - Optional disconnect options\n * @returns Promise that resolves when disconnected\n * @throws Error if disconnection fails\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.disconnect();\n * ```\n */\n disconnect(options?: DisconnectOptions): Promise<void>;\n\n /**\n * Get a list of available Wi-Fi networks from the last scan.\n * Only available on Android.\n *\n * @returns Promise that resolves with the list of networks\n * @throws Error if getting networks fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * const { networks } = await CapacitorWifi.getAvailableNetworks();\n * networks.forEach(network => {\n * console.log(`SSID: ${network.ssid}, Signal: ${network.rssi} dBm`);\n * });\n * ```\n */\n getAvailableNetworks(): Promise<GetAvailableNetworksResult>;\n\n /**\n * Get the device's current IP address.\n * Available on both Android and iOS.\n *\n * @returns Promise that resolves with the IP address\n * @throws Error if getting IP address fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const { ipAddress } = await CapacitorWifi.getIpAddress();\n * console.log('IP Address:', ipAddress);\n * ```\n */\n getIpAddress(): Promise<GetIpAddressResult>;\n\n /**\n * Get the received signal strength indicator (RSSI) of the current network in dBm.\n * Only available on Android.\n *\n * @returns Promise that resolves with the RSSI value\n * @throws Error if getting RSSI fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * const { rssi } = await CapacitorWifi.getRssi();\n * console.log('Signal strength:', rssi, 'dBm');\n * ```\n */\n getRssi(): Promise<GetRssiResult>;\n\n /**\n * Get the service set identifier (SSID) of the current network.\n * Available on both Android and iOS.\n *\n * @returns Promise that resolves with the SSID\n * @throws Error if getting SSID fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const { ssid } = await CapacitorWifi.getSsid();\n * console.log('Connected to:', ssid);\n * ```\n */\n getSsid(): Promise<GetSsidResult>;\n\n /**\n * Check if Wi-Fi is enabled on the device.\n * Only available on Android.\n *\n * @returns Promise that resolves with the Wi-Fi enabled status\n * @throws Error if checking status fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * const { enabled } = await CapacitorWifi.isEnabled();\n * console.log('WiFi is', enabled ? 'enabled' : 'disabled');\n * ```\n */\n isEnabled(): Promise<IsEnabledResult>;\n\n /**\n * Start scanning for Wi-Fi networks.\n * Only available on Android.\n * Results are delivered via the 'networksScanned' event listener.\n * Note: May fail due to system throttling or hardware issues.\n *\n * @returns Promise that resolves when scan starts\n * @throws Error if scan fails or on unsupported platform\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.addListener('networksScanned', () => {\n * console.log('Scan completed');\n * });\n * await CapacitorWifi.startScan();\n * ```\n */\n startScan(): Promise<void>;\n\n /**\n * Check the current permission status for location access.\n * Location permission is required for Wi-Fi operations on both platforms.\n *\n * @returns Promise that resolves with the permission status\n * @throws Error if checking permissions fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const status = await CapacitorWifi.checkPermissions();\n * console.log('Location permission:', status.location);\n * ```\n */\n checkPermissions(): Promise<PermissionStatus>;\n\n /**\n * Request location permissions from the user.\n * Location permission is required for Wi-Fi operations on both platforms.\n *\n * @param options - Optional permission request options\n * @returns Promise that resolves with the updated permission status\n * @throws Error if requesting permissions fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const status = await CapacitorWifi.requestPermissions();\n * if (status.location === 'granted') {\n * console.log('Permission granted');\n * }\n * ```\n */\n requestPermissions(options?: RequestPermissionsOptions): Promise<PermissionStatus>;\n\n /**\n * Add a listener for the 'networksScanned' event.\n * Only available on Android.\n * This event is fired when Wi-Fi scan results are available.\n *\n * @param eventName - The event name ('networksScanned')\n * @param listenerFunc - The callback function to execute\n * @returns Promise that resolves with a listener handle\n * @since 7.0.0\n * @example\n * ```typescript\n * const listener = await CapacitorWifi.addListener('networksScanned', async () => {\n * const { networks } = await CapacitorWifi.getAvailableNetworks();\n * console.log('Found networks:', networks);\n * });\n * ```\n */\n addListener(eventName: 'networksScanned', listenerFunc: () => void): Promise<PluginListenerHandle>;\n\n /**\n * Remove all listeners for this plugin.\n *\n * @returns Promise that resolves when all listeners are removed\n * @since 7.0.0\n * @example\n * ```typescript\n * await CapacitorWifi.removeAllListeners();\n * ```\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Get the native plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 7.0.0\n * @example\n * ```typescript\n * const { version } = await CapacitorWifi.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n\n/**\n * Options for adding a network\n *\n * @since 7.0.0\n */\nexport interface AddNetworkOptions {\n /**\n * The SSID of the network to add\n *\n * @since 7.0.0\n */\n ssid: string;\n\n /**\n * The password for the network (optional for open networks)\n *\n * @since 7.0.0\n */\n password?: string;\n\n /**\n * Whether the network is hidden (Android only)\n *\n * @since 7.0.0\n * @default false\n */\n isHiddenSsid?: boolean;\n\n /**\n * The security type of the network (Android only)\n *\n * @since 7.0.0\n * @default NetworkSecurityType.WPA2_PSK\n */\n securityType?: NetworkSecurityType;\n}\n\n/**\n * Options for connecting to a network\n *\n * @since 7.0.0\n */\nexport interface ConnectOptions {\n /**\n * The SSID of the network to connect to\n *\n * @since 7.0.0\n */\n ssid: string;\n\n /**\n * The password for the network (optional for open networks)\n *\n * @since 7.0.0\n */\n password?: string;\n\n /**\n * Whether the network is hidden (Android only)\n *\n * @since 7.0.0\n * @default false\n */\n isHiddenSsid?: boolean;\n\n /**\n * Whether to automatically route app traffic through the connected Wi-Fi network (Android only)\n * When enabled, it binds the app process to the connected network using ConnectivityManager.bindProcessToNetwork()\n * This is useful for connecting to local/device-hosted APs (e.g., ESP32, IoT devices) that don't have internet access.\n *\n * @since 7.0.0\n * @default false\n */\n autoRouteTraffic?: boolean;\n}\n\n/**\n * Options for disconnecting from a network\n *\n * @since 7.0.0\n */\nexport interface DisconnectOptions {\n /**\n * The SSID of the network to disconnect from (optional)\n *\n * @since 7.0.0\n */\n ssid?: string;\n}\n\n/**\n * Result from getAvailableNetworks()\n *\n * @since 7.0.0\n */\nexport interface GetAvailableNetworksResult {\n /**\n * List of available networks\n *\n * @since 7.0.0\n */\n networks: Network[];\n}\n\n/**\n * Represents a Wi-Fi network\n *\n * @since 7.0.0\n */\nexport interface Network {\n /**\n * The SSID of the network\n *\n * @since 7.0.0\n */\n ssid: string;\n\n /**\n * The signal strength in dBm\n *\n * @since 7.0.0\n */\n rssi: number;\n\n /**\n * The security types supported by this network (Android SDK 33+ only)\n *\n * @since 7.0.0\n */\n securityTypes?: NetworkSecurityType[];\n}\n\n/**\n * Result from getIpAddress()\n *\n * @since 7.0.0\n */\nexport interface GetIpAddressResult {\n /**\n * The device's IP address\n *\n * @since 7.0.0\n */\n ipAddress: string;\n}\n\n/**\n * Result from getRssi()\n *\n * @since 7.0.0\n */\nexport interface GetRssiResult {\n /**\n * The signal strength in dBm\n *\n * @since 7.0.0\n */\n rssi: number;\n}\n\n/**\n * Result from getSsid()\n *\n * @since 7.0.0\n */\nexport interface GetSsidResult {\n /**\n * The SSID of the current network\n *\n * @since 7.0.0\n */\n ssid: string;\n}\n\n/**\n * Result from isEnabled()\n *\n * @since 7.0.0\n */\nexport interface IsEnabledResult {\n /**\n * Whether Wi-Fi is enabled\n *\n * @since 7.0.0\n */\n enabled: boolean;\n}\n\n/**\n * Permission status\n *\n * @since 7.0.0\n */\nexport interface PermissionStatus {\n /**\n * Location permission state\n *\n * @since 7.0.0\n */\n location: PermissionState;\n}\n\n/**\n * Possible permission states\n *\n * @since 7.0.0\n */\nexport type PermissionState = 'granted' | 'denied' | 'prompt';\n\n/**\n * Options for requesting permissions\n *\n * @since 7.0.0\n */\nexport interface RequestPermissionsOptions {\n /**\n * Permissions to request\n *\n * @since 7.0.0\n */\n permissions?: 'location'[];\n}\n\n/**\n * Network security types\n *\n * @since 7.0.0\n */\nexport enum NetworkSecurityType {\n /**\n * Open network with no security\n *\n * @since 7.0.0\n */\n OPEN = 0,\n\n /**\n * WEP security\n *\n * @since 7.0.0\n */\n WEP = 1,\n\n /**\n * WPA/WPA2 Personal (PSK)\n *\n * @since 7.0.0\n */\n WPA2_PSK = 2,\n\n /**\n * WPA/WPA2/WPA3 Enterprise (EAP)\n *\n * @since 7.0.0\n */\n EAP = 3,\n\n /**\n * WPA3 Personal (SAE)\n *\n * @since 7.0.0\n */\n SAE = 4,\n\n /**\n * WPA3 Enterprise\n *\n * @since 7.0.0\n */\n WPA3_ENTERPRISE = 5,\n\n /**\n * WPA3 Enterprise 192-bit mode\n *\n * @since 7.0.0\n */\n WPA3_ENTERPRISE_192_BIT = 6,\n\n /**\n * Passpoint network\n *\n * @since 7.0.0\n */\n PASSPOINT = 7,\n\n /**\n * Enhanced Open (OWE)\n *\n * @since 7.0.0\n */\n OWE = 8,\n\n /**\n * WAPI PSK\n *\n * @since 7.0.0\n */\n WAPI_PSK = 9,\n\n /**\n * WAPI Certificate\n *\n * @since 7.0.0\n */\n WAPI_CERT = 10,\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import CoreLocation
|
|
|
6
6
|
|
|
7
7
|
@objc(CapacitorWifiPlugin)
|
|
8
8
|
public class CapacitorWifiPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
9
|
-
private let pluginVersion: String = "8.0
|
|
9
|
+
private let pluginVersion: String = "8.1.0"
|
|
10
10
|
public let identifier = "CapacitorWifiPlugin"
|
|
11
11
|
public let jsName = "CapacitorWifi"
|
|
12
12
|
public let pluginMethods: [CAPPluginMethod] = [
|
package/package.json
CHANGED
|
@@ -1,439 +0,0 @@
|
|
|
1
|
-
package app.capgo.capacitorwifi;
|
|
2
|
-
|
|
3
|
-
import android.Manifest;
|
|
4
|
-
import android.content.BroadcastReceiver;
|
|
5
|
-
import android.content.Context;
|
|
6
|
-
import android.content.Intent;
|
|
7
|
-
import android.content.IntentFilter;
|
|
8
|
-
import android.net.ConnectivityManager;
|
|
9
|
-
import android.net.Network;
|
|
10
|
-
import android.net.NetworkCapabilities;
|
|
11
|
-
import android.net.NetworkRequest;
|
|
12
|
-
import android.net.NetworkSpecifier;
|
|
13
|
-
import android.net.wifi.ScanResult;
|
|
14
|
-
import android.net.wifi.WifiConfiguration;
|
|
15
|
-
import android.net.wifi.WifiManager;
|
|
16
|
-
import android.net.wifi.WifiNetworkSpecifier;
|
|
17
|
-
import android.os.Build;
|
|
18
|
-
import android.provider.Settings;
|
|
19
|
-
import androidx.annotation.NonNull;
|
|
20
|
-
import androidx.annotation.RequiresApi;
|
|
21
|
-
import com.getcapacitor.JSArray;
|
|
22
|
-
import com.getcapacitor.JSObject;
|
|
23
|
-
import com.getcapacitor.PermissionState;
|
|
24
|
-
import com.getcapacitor.Plugin;
|
|
25
|
-
import com.getcapacitor.PluginCall;
|
|
26
|
-
import com.getcapacitor.PluginMethod;
|
|
27
|
-
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
28
|
-
import com.getcapacitor.annotation.Permission;
|
|
29
|
-
import com.getcapacitor.annotation.PermissionCallback;
|
|
30
|
-
import java.net.InetAddress;
|
|
31
|
-
import java.net.NetworkInterface;
|
|
32
|
-
import java.util.Enumeration;
|
|
33
|
-
import java.util.List;
|
|
34
|
-
|
|
35
|
-
@CapacitorPlugin(
|
|
36
|
-
name = "CapacitorWifi",
|
|
37
|
-
permissions = {
|
|
38
|
-
@Permission(
|
|
39
|
-
alias = "location",
|
|
40
|
-
strings = {
|
|
41
|
-
Manifest.permission.ACCESS_FINE_LOCATION,
|
|
42
|
-
Manifest.permission.ACCESS_COARSE_LOCATION,
|
|
43
|
-
Manifest.permission.ACCESS_WIFI_STATE,
|
|
44
|
-
Manifest.permission.CHANGE_WIFI_STATE
|
|
45
|
-
}
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
)
|
|
49
|
-
public class CapacitorWifiPlugin extends Plugin {
|
|
50
|
-
|
|
51
|
-
private final String pluginVersion = "7.0.0";
|
|
52
|
-
private WifiManager wifiManager;
|
|
53
|
-
private ConnectivityManager connectivityManager;
|
|
54
|
-
private BroadcastReceiver scanResultsReceiver;
|
|
55
|
-
private ConnectivityManager.NetworkCallback networkCallback;
|
|
56
|
-
|
|
57
|
-
@Override
|
|
58
|
-
public void load() {
|
|
59
|
-
wifiManager = (WifiManager) getContext().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
|
60
|
-
connectivityManager = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
61
|
-
|
|
62
|
-
// Set up scan results receiver
|
|
63
|
-
scanResultsReceiver = new BroadcastReceiver() {
|
|
64
|
-
@Override
|
|
65
|
-
public void onReceive(Context context, Intent intent) {
|
|
66
|
-
notifyListeners("networksScanned", new JSObject());
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
@PluginMethod
|
|
72
|
-
public void addNetwork(PluginCall call) {
|
|
73
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
74
|
-
// Android 10+ - use system dialog
|
|
75
|
-
addNetworkModern(call);
|
|
76
|
-
} else {
|
|
77
|
-
// Pre-Android 10 - programmatic approach
|
|
78
|
-
addNetworkLegacy(call);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@RequiresApi(api = Build.VERSION_CODES.Q)
|
|
83
|
-
private void addNetworkModern(PluginCall call) {
|
|
84
|
-
String ssid = call.getString("ssid");
|
|
85
|
-
if (ssid == null) {
|
|
86
|
-
call.reject("SSID is required");
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Open WiFi settings with SSID
|
|
91
|
-
Intent intent = new Intent(Settings.ACTION_WIFI_ADD_NETWORKS);
|
|
92
|
-
intent.putExtra(Settings.EXTRA_WIFI_NETWORK_LIST, new String[] { ssid });
|
|
93
|
-
getActivity().startActivity(intent);
|
|
94
|
-
call.resolve();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private void addNetworkLegacy(PluginCall call) {
|
|
98
|
-
String ssid = call.getString("ssid");
|
|
99
|
-
String password = call.getString("password");
|
|
100
|
-
Boolean isHidden = call.getBoolean("isHiddenSsid", false);
|
|
101
|
-
|
|
102
|
-
if (ssid == null) {
|
|
103
|
-
call.reject("SSID is required");
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
108
|
-
requestPermissionForAlias("location", call, "addNetworkCallback");
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
WifiConfiguration config = new WifiConfiguration();
|
|
113
|
-
config.SSID = "\"" + ssid + "\"";
|
|
114
|
-
config.hiddenSSID = isHidden;
|
|
115
|
-
|
|
116
|
-
if (password != null && !password.isEmpty()) {
|
|
117
|
-
config.preSharedKey = "\"" + password + "\"";
|
|
118
|
-
} else {
|
|
119
|
-
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
int netId = wifiManager.addNetwork(config);
|
|
123
|
-
if (netId == -1) {
|
|
124
|
-
call.reject("Failed to add network");
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
boolean enabled = wifiManager.enableNetwork(netId, true);
|
|
129
|
-
if (!enabled) {
|
|
130
|
-
call.reject("Failed to enable network");
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
call.resolve();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
@PermissionCallback
|
|
138
|
-
private void addNetworkCallback(PluginCall call) {
|
|
139
|
-
if (getPermissionState("location") == PermissionState.GRANTED) {
|
|
140
|
-
addNetworkLegacy(call);
|
|
141
|
-
} else {
|
|
142
|
-
call.reject("Location permission is required");
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
@PluginMethod
|
|
147
|
-
public void connect(PluginCall call) {
|
|
148
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
149
|
-
connectModern(call);
|
|
150
|
-
} else {
|
|
151
|
-
connectLegacy(call);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
@RequiresApi(api = Build.VERSION_CODES.Q)
|
|
156
|
-
private void connectModern(PluginCall call) {
|
|
157
|
-
String ssid = call.getString("ssid");
|
|
158
|
-
String password = call.getString("password");
|
|
159
|
-
|
|
160
|
-
if (ssid == null) {
|
|
161
|
-
call.reject("SSID is required");
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
WifiNetworkSpecifier.Builder specifierBuilder = new WifiNetworkSpecifier.Builder().setSsid(ssid);
|
|
166
|
-
|
|
167
|
-
if (password != null && !password.isEmpty()) {
|
|
168
|
-
specifierBuilder.setWpa2Passphrase(password);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
NetworkSpecifier specifier = specifierBuilder.build();
|
|
172
|
-
|
|
173
|
-
NetworkRequest request = new NetworkRequest.Builder()
|
|
174
|
-
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
|
175
|
-
.setNetworkSpecifier(specifier)
|
|
176
|
-
.build();
|
|
177
|
-
|
|
178
|
-
networkCallback = new ConnectivityManager.NetworkCallback() {
|
|
179
|
-
@Override
|
|
180
|
-
public void onAvailable(@NonNull Network network) {
|
|
181
|
-
super.onAvailable(network);
|
|
182
|
-
call.resolve();
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
@Override
|
|
186
|
-
public void onUnavailable() {
|
|
187
|
-
super.onUnavailable();
|
|
188
|
-
call.reject("Network unavailable");
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
connectivityManager.requestNetwork(request, networkCallback);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
private void connectLegacy(PluginCall call) {
|
|
196
|
-
addNetworkLegacy(call);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
@PluginMethod
|
|
200
|
-
public void disconnect(PluginCall call) {
|
|
201
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
202
|
-
if (networkCallback != null) {
|
|
203
|
-
connectivityManager.unregisterNetworkCallback(networkCallback);
|
|
204
|
-
networkCallback = null;
|
|
205
|
-
}
|
|
206
|
-
} else {
|
|
207
|
-
wifiManager.disconnect();
|
|
208
|
-
}
|
|
209
|
-
call.resolve();
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
@PluginMethod
|
|
213
|
-
public void getAvailableNetworks(PluginCall call) {
|
|
214
|
-
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
215
|
-
requestPermissionForAlias("location", call, "getAvailableNetworksCallback");
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
getAvailableNetworksWithPermission(call);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
@PermissionCallback
|
|
223
|
-
private void getAvailableNetworksCallback(PluginCall call) {
|
|
224
|
-
if (getPermissionState("location") == PermissionState.GRANTED) {
|
|
225
|
-
getAvailableNetworksWithPermission(call);
|
|
226
|
-
} else {
|
|
227
|
-
call.reject("Location permission is required");
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
private void getAvailableNetworksWithPermission(PluginCall call) {
|
|
232
|
-
List<ScanResult> results = wifiManager.getScanResults();
|
|
233
|
-
JSArray networks = new JSArray();
|
|
234
|
-
|
|
235
|
-
for (ScanResult result : results) {
|
|
236
|
-
JSObject network = new JSObject();
|
|
237
|
-
network.put("ssid", result.SSID);
|
|
238
|
-
network.put("rssi", result.level);
|
|
239
|
-
|
|
240
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
241
|
-
JSArray securityTypes = new JSArray();
|
|
242
|
-
// Add security types based on capabilities
|
|
243
|
-
String capabilities = result.capabilities;
|
|
244
|
-
if (capabilities.contains("WPA3")) {
|
|
245
|
-
securityTypes.put(4); // SAE
|
|
246
|
-
} else if (capabilities.contains("WPA2")) {
|
|
247
|
-
securityTypes.put(2); // WPA2_PSK
|
|
248
|
-
} else if (capabilities.contains("WPA")) {
|
|
249
|
-
securityTypes.put(2); // WPA2_PSK
|
|
250
|
-
} else if (capabilities.contains("WEP")) {
|
|
251
|
-
securityTypes.put(1); // WEP
|
|
252
|
-
} else {
|
|
253
|
-
securityTypes.put(0); // OPEN
|
|
254
|
-
}
|
|
255
|
-
network.put("securityTypes", securityTypes);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
networks.put(network);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
JSObject result = new JSObject();
|
|
262
|
-
result.put("networks", networks);
|
|
263
|
-
call.resolve(result);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
@PluginMethod
|
|
267
|
-
public void getIpAddress(PluginCall call) {
|
|
268
|
-
try {
|
|
269
|
-
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
|
|
270
|
-
NetworkInterface intf = en.nextElement();
|
|
271
|
-
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
|
|
272
|
-
InetAddress inetAddress = enumIpAddr.nextElement();
|
|
273
|
-
if (!inetAddress.isLoopbackAddress() && inetAddress.getAddress().length == 4) {
|
|
274
|
-
String ip = inetAddress.getHostAddress();
|
|
275
|
-
JSObject result = new JSObject();
|
|
276
|
-
result.put("ipAddress", ip);
|
|
277
|
-
call.resolve(result);
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
call.reject("No IP address found");
|
|
283
|
-
} catch (Exception e) {
|
|
284
|
-
call.reject("Failed to get IP address", e);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
@PluginMethod
|
|
289
|
-
public void getRssi(PluginCall call) {
|
|
290
|
-
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
291
|
-
requestPermissionForAlias("location", call, "getRssiCallback");
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
getRssiWithPermission(call);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
@PermissionCallback
|
|
299
|
-
private void getRssiCallback(PluginCall call) {
|
|
300
|
-
if (getPermissionState("location") == PermissionState.GRANTED) {
|
|
301
|
-
getRssiWithPermission(call);
|
|
302
|
-
} else {
|
|
303
|
-
call.reject("Location permission is required");
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
private void getRssiWithPermission(PluginCall call) {
|
|
308
|
-
android.net.wifi.WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
|
309
|
-
int rssi = wifiInfo.getRssi();
|
|
310
|
-
|
|
311
|
-
JSObject result = new JSObject();
|
|
312
|
-
result.put("rssi", rssi);
|
|
313
|
-
call.resolve(result);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
@PluginMethod
|
|
317
|
-
public void getSsid(PluginCall call) {
|
|
318
|
-
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
319
|
-
requestPermissionForAlias("location", call, "getSsidCallback");
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
getSsidWithPermission(call);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
@PermissionCallback
|
|
327
|
-
private void getSsidCallback(PluginCall call) {
|
|
328
|
-
if (getPermissionState("location") == PermissionState.GRANTED) {
|
|
329
|
-
getSsidWithPermission(call);
|
|
330
|
-
} else {
|
|
331
|
-
call.reject("Location permission is required");
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
private void getSsidWithPermission(PluginCall call) {
|
|
336
|
-
android.net.wifi.WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
|
337
|
-
String ssid = wifiInfo.getSSID();
|
|
338
|
-
|
|
339
|
-
// Remove quotes if present
|
|
340
|
-
if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
|
|
341
|
-
ssid = ssid.substring(1, ssid.length() - 1);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
JSObject result = new JSObject();
|
|
345
|
-
result.put("ssid", ssid);
|
|
346
|
-
call.resolve(result);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
@PluginMethod
|
|
350
|
-
public void isEnabled(PluginCall call) {
|
|
351
|
-
boolean enabled = wifiManager.isWifiEnabled();
|
|
352
|
-
|
|
353
|
-
JSObject result = new JSObject();
|
|
354
|
-
result.put("enabled", enabled);
|
|
355
|
-
call.resolve(result);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
@PluginMethod
|
|
359
|
-
public void startScan(PluginCall call) {
|
|
360
|
-
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
361
|
-
requestPermissionForAlias("location", call, "startScanCallback");
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
startScanWithPermission(call);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
@PermissionCallback
|
|
369
|
-
private void startScanCallback(PluginCall call) {
|
|
370
|
-
if (getPermissionState("location") == PermissionState.GRANTED) {
|
|
371
|
-
startScanWithPermission(call);
|
|
372
|
-
} else {
|
|
373
|
-
call.reject("Location permission is required");
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
private void startScanWithPermission(PluginCall call) {
|
|
378
|
-
// Register receiver
|
|
379
|
-
getContext().registerReceiver(scanResultsReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
|
|
380
|
-
|
|
381
|
-
boolean success = wifiManager.startScan();
|
|
382
|
-
if (success) {
|
|
383
|
-
call.resolve();
|
|
384
|
-
} else {
|
|
385
|
-
call.reject("Failed to start scan");
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
@PluginMethod
|
|
390
|
-
public void checkPermissions(PluginCall call) {
|
|
391
|
-
JSObject result = new JSObject();
|
|
392
|
-
result.put("location", getPermissionState("location").toString().toLowerCase());
|
|
393
|
-
call.resolve(result);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
@PluginMethod
|
|
397
|
-
public void requestPermissions(PluginCall call) {
|
|
398
|
-
if (getPermissionState("location") == PermissionState.GRANTED) {
|
|
399
|
-
JSObject result = new JSObject();
|
|
400
|
-
result.put("location", "granted");
|
|
401
|
-
call.resolve(result);
|
|
402
|
-
} else {
|
|
403
|
-
requestPermissionForAlias("location", call, "permissionsCallback");
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
@PermissionCallback
|
|
408
|
-
private void permissionsCallback(PluginCall call) {
|
|
409
|
-
JSObject result = new JSObject();
|
|
410
|
-
result.put("location", getPermissionState("location").toString().toLowerCase());
|
|
411
|
-
call.resolve(result);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
@PluginMethod
|
|
415
|
-
public void getPluginVersion(final PluginCall call) {
|
|
416
|
-
try {
|
|
417
|
-
final JSObject result = new JSObject();
|
|
418
|
-
result.put("version", this.pluginVersion);
|
|
419
|
-
call.resolve(result);
|
|
420
|
-
} catch (final Exception e) {
|
|
421
|
-
call.reject("Could not get plugin version", e);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
@Override
|
|
426
|
-
protected void handleOnDestroy() {
|
|
427
|
-
try {
|
|
428
|
-
if (scanResultsReceiver != null) {
|
|
429
|
-
getContext().unregisterReceiver(scanResultsReceiver);
|
|
430
|
-
}
|
|
431
|
-
if (networkCallback != null) {
|
|
432
|
-
connectivityManager.unregisterNetworkCallback(networkCallback);
|
|
433
|
-
}
|
|
434
|
-
} catch (Exception e) {
|
|
435
|
-
// Receiver might not be registered
|
|
436
|
-
}
|
|
437
|
-
super.handleOnDestroy();
|
|
438
|
-
}
|
|
439
|
-
}
|