fixed ios wifi part support. retry 9.

This commit is contained in:
aria committed 2026-04-23 12:03:31 +09:00
1 parent a229e05186
commit 1c5946620f
4 files changed
+53 -3

No files matched your search

+1
View File
@@ -214,6 +214,7 @@ iOS WiFi:
- 插件将 iOS deployment target 设置为 `15.0`;如果宿主 App 或构建平台覆盖该值,需要在宿主配置中同步设置 iOS 最低版本为 15.0 或更高。 - 插件将 iOS deployment target 设置为 `15.0`;如果宿主 App 或构建平台覆盖该值,需要在宿主配置中同步设置 iOS 最低版本为 15.0 或更高。
- 插件会向 Cordova iOS entitlements 写入 `com.apple.developer.networking.HotspotConfiguration`,但仍必须在 Apple Developer App ID 中开启 `Hotspot Configuration` capability,并使用包含该 capability 的 provisioning profile 重新构建。 - 插件会向 Cordova iOS entitlements 写入 `com.apple.developer.networking.HotspotConfiguration`,但仍必须在 Apple Developer App ID 中开启 `Hotspot Configuration` capability,并使用包含该 capability 的 provisioning profile 重新构建。
- 如果 iOS 返回 `NEHotspotConfigurationErrorDomain` code `8` / `internal error`,优先检查 App ID、entitlements、provisioning profile 是否都包含 `Hotspot Configuration`,并确认是在真机前台运行,不是在模拟器中测试。若签名和参数都正确,常见原因是真实热点使用 WPA2/WPA3 transition mode、WPA3 Personal、iPhone Personal Hotspot 默认安全模式,或其他 `NEHotspotConfiguration` 无法表达的 WiFi 能力。 - 如果 iOS 返回 `NEHotspotConfigurationErrorDomain` code `8` / `internal error`,优先检查 App ID、entitlements、provisioning profile 是否都包含 `Hotspot Configuration`,并确认是在真机前台运行,不是在模拟器中测试。若签名和参数都正确,常见原因是真实热点使用 WPA2/WPA3 transition mode、WPA3 Personal、iPhone Personal Hotspot 默认安全模式,或其他 `NEHotspotConfiguration` 无法表达的 WiFi 能力。
- iOS 错误结果会包含 `applicationState`、`ssidUtf8Length`、`passwordUtf8Length`、`passwordAsciiPrintable` 等诊断字段;WPA/WPA2 密码建议使用 8-63 位可打印 ASCII 字符。
- iOS 的 `NEHotspotConfiguration` password initializer 公开支持 WEP/WPA/WPA2 Personal,不提供 WPA3 Personal 参数。iOS 传入 `security` 包含 `wpa3` 时会返回 `UNSUPPORTED_WIFI_SECURITY`。WPA2/WPA3 mixed 通常只能按 `security: "wpa2"` 尝试;如果仍失败,需要用户手动加入,或改用配置描述文件/MDM 流程。 - iOS 的 `NEHotspotConfiguration` password initializer 公开支持 WEP/WPA/WPA2 Personal,不提供 WPA3 Personal 参数。iOS 传入 `security` 包含 `wpa3` 时会返回 `UNSUPPORTED_WIFI_SECURITY`。WPA2/WPA3 mixed 通常只能按 `security: "wpa2"` 尝试;如果仍失败,需要用户手动加入,或改用配置描述文件/MDM 流程。
- iOS 不提供第三方 App 断开当前 WiFi 的公开 API,因此 `disconnectWifi` 在 iOS 返回错误。 - iOS 不提供第三方 App 断开当前 WiFi 的公开 API,因此 `disconnectWifi` 在 iOS 返回错误。
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "bluememe-utils", "name": "bluememe-utils",
"version": "0.1.8", "version": "0.1.9",
"description": "Cordova utilities for WiFi, Firebase Cloud Messaging, and biometric unlock for OutSystems 11 apps.", "description": "Cordova utilities for WiFi, Firebase Cloud Messaging, and biometric unlock for OutSystems 11 apps.",
"license": "MIT", "license": "MIT",
"files": [ "files": [
+1 -1
View File
@@ -2,7 +2,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
id="bluememe-utils" id="bluememe-utils"
version="0.1.8"> version="0.1.9">
<name>bluememe-utils</name> <name>bluememe-utils</name>
<description>Cordova utilities for WiFi, Firebase Cloud Messaging, and biometric unlock.</description> <description>Cordova utilities for WiFi, Firebase Cloud Messaging, and biometric unlock.</description>
<license>MIT</license> <license>MIT</license>
+50 -1
View File
@@ -294,12 +294,27 @@ static NSString * const BluememeDeviceKeyDefaultsKey = @"bluememe_utils_device_k
BOOL isWep = [security isEqualToString:@"wep"] || [self boolFromDictionary:options key:@"isWep" defaultValue:NO]; BOOL isWep = [security isEqualToString:@"wep"] || [self boolFromDictionary:options key:@"isWep" defaultValue:NO];
BOOL joinOnce = [self boolFromDictionary:options key:@"joinOnce" defaultValue:defaultJoinOnce]; BOOL joinOnce = [self boolFromDictionary:options key:@"joinOnce" defaultValue:defaultJoinOnce];
BOOL hiddenSsid = [self boolFromDictionary:options key:@"hiddenSsid" defaultValue:NO]; BOOL hiddenSsid = [self boolFromDictionary:options key:@"hiddenSsid" defaultValue:NO];
NSString *applicationState = [self applicationStateName];
if (ssid.length == 0) { if (ssid.length == 0) {
[self sendErrorForCommand:command code:@"INVALID_WIFI_OPTIONS" message:@"ssid is required."]; [self sendErrorForCommand:command code:@"INVALID_WIFI_OPTIONS" message:@"ssid is required."];
return; return;
} }
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) {
[self sendErrorForCommand:command
code:@"APPLICATION_NOT_ACTIVE"
message:@"iOS WiFi configuration must be requested while the app is active in the foreground."
details:@{
@"ssid": ssid,
@"security": security,
@"joinOnce": @(joinOnce),
@"hiddenSsid": @(hiddenSsid),
@"applicationState": applicationState
}];
return;
}
if (isWpa3) { if (isWpa3) {
[self sendErrorForCommand:command [self sendErrorForCommand:command
code:@"UNSUPPORTED_WIFI_SECURITY" code:@"UNSUPPORTED_WIFI_SECURITY"
@@ -348,9 +363,13 @@ static NSString * const BluememeDeviceKeyDefaultsKey = @"bluememe_utils_device_k
@"ssid": ssid, @"ssid": ssid,
@"security": security, @"security": security,
@"passwordLength": @(password.length), @"passwordLength": @(password.length),
@"passwordUtf8Length": @([password lengthOfBytesUsingEncoding:NSUTF8StringEncoding]),
@"passwordAsciiPrintable": @([self isAsciiPrintableString:password]),
@"ssidUtf8Length": @([ssid lengthOfBytesUsingEncoding:NSUTF8StringEncoding]),
@"joinOnce": @(joinOnce), @"joinOnce": @(joinOnce),
@"hiddenSsid": @(hiddenSsid), @"hiddenSsid": @(hiddenSsid),
@"minimumIos": @"15.0" @"minimumIos": @"15.0",
@"applicationState": applicationState
}; };
[self sendWifiApplyErrorForCommand:command error:error context:context]; [self sendWifiApplyErrorForCommand:command error:error context:context];
return; return;
@@ -377,6 +396,36 @@ static NSString * const BluememeDeviceKeyDefaultsKey = @"bluememe_utils_device_k
} }
} }
- (NSString *)applicationStateName
{
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
switch (state) {
case UIApplicationStateActive:
return @"active";
case UIApplicationStateInactive:
return @"inactive";
case UIApplicationStateBackground:
return @"background";
default:
return @"unknown";
}
}
- (BOOL)isAsciiPrintableString:(NSString *)value
{
if (value.length == 0) {
return YES;
}
for (NSUInteger index = 0; index < value.length; index++) {
unichar character = [value characterAtIndex:index];
if (character < 0x20 || character > 0x7E) {
return NO;
}
}
return YES;
}
- (void)sendWifiApplyErrorForCommand:(CDVInvokedUrlCommand *)command error:(NSError *)error context:(NSDictionary *)context - (void)sendWifiApplyErrorForCommand:(CDVInvokedUrlCommand *)command error:(NSError *)error context:(NSDictionary *)context
{ {
NSMutableDictionary *details = [NSMutableDictionary dictionary]; NSMutableDictionary *details = [NSMutableDictionary dictionary];